1use crate::types::ReferenceCellType;
13use rlst::RlstScalar;
14
15pub fn dim(cell: ReferenceCellType) -> usize {
17 match cell {
18 ReferenceCellType::Point => 0,
19 ReferenceCellType::Interval => 1,
20 ReferenceCellType::Triangle => 2,
21 ReferenceCellType::Quadrilateral => 2,
22 ReferenceCellType::Tetrahedron => 3,
23 ReferenceCellType::Hexahedron => 3,
24 ReferenceCellType::Prism => 3,
25 ReferenceCellType::Pyramid => 3,
26 }
27}
28pub fn is_simplex(cell: ReferenceCellType) -> bool {
30 match cell {
31 ReferenceCellType::Point => true,
32 ReferenceCellType::Interval => true,
33 ReferenceCellType::Triangle => true,
34 ReferenceCellType::Quadrilateral => false,
35 ReferenceCellType::Tetrahedron => true,
36 ReferenceCellType::Hexahedron => false,
37 ReferenceCellType::Prism => false,
38 ReferenceCellType::Pyramid => false,
39 }
40}
41
42pub fn vertices<T: RlstScalar>(cell: ReferenceCellType) -> Vec<Vec<T>> {
44 let zero = T::from(0.0).unwrap();
45 let one = T::from(1.0).unwrap();
46 match cell {
47 ReferenceCellType::Point => vec![],
48 ReferenceCellType::Interval => vec![vec![zero], vec![one]],
49 ReferenceCellType::Triangle => vec![vec![zero, zero], vec![one, zero], vec![zero, one]],
50 ReferenceCellType::Quadrilateral => vec![
51 vec![zero, zero],
52 vec![one, zero],
53 vec![zero, one],
54 vec![one, one],
55 ],
56 ReferenceCellType::Tetrahedron => vec![
57 vec![zero, zero, zero],
58 vec![one, zero, zero],
59 vec![zero, one, zero],
60 vec![zero, zero, one],
61 ],
62 ReferenceCellType::Hexahedron => vec![
63 vec![zero, zero, zero],
64 vec![one, zero, zero],
65 vec![zero, one, zero],
66 vec![one, one, zero],
67 vec![zero, zero, one],
68 vec![one, zero, one],
69 vec![zero, one, one],
70 vec![one, one, one],
71 ],
72 ReferenceCellType::Prism => vec![
73 vec![zero, zero, zero],
74 vec![one, zero, zero],
75 vec![zero, one, zero],
76 vec![zero, zero, one],
77 vec![one, zero, one],
78 vec![zero, one, one],
79 ],
80 ReferenceCellType::Pyramid => vec![
81 vec![zero, zero, zero],
82 vec![one, zero, zero],
83 vec![zero, one, zero],
84 vec![one, one, zero],
85 vec![zero, zero, one],
86 ],
87 }
88}
89
90pub fn midpoint<T: RlstScalar>(cell: ReferenceCellType) -> Vec<T> {
92 let half = T::from(0.5).unwrap();
93 let third = T::from(1.0).unwrap() / T::from(3.0).unwrap();
94 match cell {
95 ReferenceCellType::Point => vec![],
96 ReferenceCellType::Interval => vec![half],
97 ReferenceCellType::Triangle => vec![third; 2],
98 ReferenceCellType::Quadrilateral => vec![half; 2],
99 ReferenceCellType::Tetrahedron => vec![T::from(1.0).unwrap() / T::from(4.0).unwrap(); 3],
100 ReferenceCellType::Hexahedron => vec![half; 3],
101 ReferenceCellType::Prism => vec![third, third, half],
102 ReferenceCellType::Pyramid => vec![
103 T::from(0.4).unwrap(),
104 T::from(0.4).unwrap(),
105 T::from(0.2).unwrap(),
106 ],
107 }
108}
109
110pub fn edges(cell: ReferenceCellType) -> Vec<Vec<usize>> {
112 match cell {
113 ReferenceCellType::Point => vec![],
114 ReferenceCellType::Interval => vec![vec![0, 1]],
115 ReferenceCellType::Triangle => vec![vec![1, 2], vec![0, 2], vec![0, 1]],
116 ReferenceCellType::Quadrilateral => vec![vec![0, 1], vec![0, 2], vec![1, 3], vec![2, 3]],
117 ReferenceCellType::Tetrahedron => vec![
118 vec![2, 3],
119 vec![1, 3],
120 vec![1, 2],
121 vec![0, 3],
122 vec![0, 2],
123 vec![0, 1],
124 ],
125 ReferenceCellType::Hexahedron => vec![
126 vec![0, 1],
127 vec![0, 2],
128 vec![0, 4],
129 vec![1, 3],
130 vec![1, 5],
131 vec![2, 3],
132 vec![2, 6],
133 vec![3, 7],
134 vec![4, 5],
135 vec![4, 6],
136 vec![5, 7],
137 vec![6, 7],
138 ],
139 ReferenceCellType::Prism => vec![
140 vec![0, 1],
141 vec![0, 2],
142 vec![0, 3],
143 vec![1, 2],
144 vec![1, 4],
145 vec![2, 5],
146 vec![3, 4],
147 vec![3, 5],
148 vec![4, 5],
149 ],
150 ReferenceCellType::Pyramid => vec![
151 vec![0, 1],
152 vec![0, 2],
153 vec![0, 4],
154 vec![1, 3],
155 vec![1, 4],
156 vec![2, 3],
157 vec![2, 4],
158 vec![3, 4],
159 ],
160 }
161}
162
163pub fn faces(cell: ReferenceCellType) -> Vec<Vec<usize>> {
165 match cell {
166 ReferenceCellType::Point => vec![],
167 ReferenceCellType::Interval => vec![],
168 ReferenceCellType::Triangle => vec![vec![0, 1, 2]],
169 ReferenceCellType::Quadrilateral => vec![vec![0, 1, 2, 3]],
170 ReferenceCellType::Tetrahedron => {
171 vec![vec![1, 2, 3], vec![0, 2, 3], vec![0, 1, 3], vec![0, 1, 2]]
172 }
173 ReferenceCellType::Hexahedron => vec![
174 vec![0, 1, 2, 3],
175 vec![0, 1, 4, 5],
176 vec![0, 2, 4, 6],
177 vec![1, 3, 5, 7],
178 vec![2, 3, 6, 7],
179 vec![4, 5, 6, 7],
180 ],
181 ReferenceCellType::Prism => vec![
182 vec![0, 1, 2],
183 vec![0, 1, 3, 4],
184 vec![0, 2, 3, 5],
185 vec![1, 2, 4, 5],
186 vec![3, 4, 5],
187 ],
188 ReferenceCellType::Pyramid => vec![
189 vec![0, 1, 2, 3],
190 vec![0, 1, 4],
191 vec![0, 2, 4],
192 vec![1, 3, 4],
193 vec![2, 3, 4],
194 ],
195 }
196}
197
198pub fn volumes(cell: ReferenceCellType) -> Vec<Vec<usize>> {
200 match cell {
201 ReferenceCellType::Point => vec![],
202 ReferenceCellType::Interval => vec![],
203 ReferenceCellType::Triangle => vec![],
204 ReferenceCellType::Quadrilateral => vec![],
205 ReferenceCellType::Tetrahedron => vec![vec![0, 1, 2, 3]],
206 ReferenceCellType::Hexahedron => vec![vec![0, 1, 2, 3, 4, 5, 6, 7]],
207 ReferenceCellType::Prism => vec![vec![0, 1, 2, 3, 4, 5]],
208 ReferenceCellType::Pyramid => vec![vec![0, 1, 2, 3, 4]],
209 }
210}
211
212pub fn facets(cell: ReferenceCellType) -> Vec<Vec<usize>> {
214 match dim(cell) {
215 0 => vec![],
216 1 => volumes(cell)[0]
217 .iter()
218 .map(|x| vec![*x])
219 .collect::<Vec<_>>(),
220 2 => edges(cell),
221 3 => faces(cell),
222 _ => {
223 panic!("Invalid dimension");
224 }
225 }
226}
227
228pub fn ridges(cell: ReferenceCellType) -> Vec<Vec<usize>> {
230 match dim(cell) {
231 0 => vec![],
232 1 => vec![],
233 2 => volumes(cell)[0]
234 .iter()
235 .map(|x| vec![*x])
236 .collect::<Vec<_>>(),
237 3 => edges(cell),
238 _ => {
239 panic!("Invalid dimension");
240 }
241 }
242}
243
244pub fn peaks(cell: ReferenceCellType) -> Vec<Vec<usize>> {
246 match dim(cell) {
247 0 => vec![],
248 1 => vec![],
249 2 => vec![],
250 3 => volumes(cell)[0]
251 .iter()
252 .map(|x| vec![*x])
253 .collect::<Vec<_>>(),
254 _ => {
255 panic!("Invalid dimension");
256 }
257 }
258}
259
260pub fn facet_normals<T: RlstScalar>(cell: ReferenceCellType) -> Vec<Vec<T>> {
262 let zero = T::from(0.0).unwrap();
263 let one = T::from(1.0).unwrap();
264 match cell {
265 ReferenceCellType::Point => vec![],
266 ReferenceCellType::Interval => vec![vec![one], vec![one]],
267 ReferenceCellType::Triangle => vec![vec![-one, -one], vec![-one, zero], vec![zero, one]],
268 ReferenceCellType::Quadrilateral => vec![
269 vec![zero, one],
270 vec![-one, zero],
271 vec![-one, zero],
272 vec![zero, one],
273 ],
274 ReferenceCellType::Tetrahedron => vec![
275 vec![one, one, one],
276 vec![one, zero, zero],
277 vec![zero, -one, zero],
278 vec![zero, zero, one],
279 ],
280 ReferenceCellType::Hexahedron => vec![
281 vec![zero, zero, one],
282 vec![zero, -one, zero],
283 vec![one, zero, zero],
284 vec![one, zero, zero],
285 vec![zero, -one, zero],
286 vec![zero, zero, one],
287 ],
288 ReferenceCellType::Prism => vec![
289 vec![zero, zero, one],
290 vec![zero, -one, zero],
291 vec![one, zero, zero],
292 vec![one, one, zero],
293 vec![zero, zero, one],
294 ],
295 ReferenceCellType::Pyramid => vec![
296 vec![zero, zero, one],
297 vec![zero, -one, zero],
298 vec![one, zero, zero],
299 vec![one, zero, one],
300 vec![zero, -one, -one],
301 ],
302 }
303}
304
305pub fn facet_unit_normals<T: RlstScalar>(cell: ReferenceCellType) -> Vec<Vec<T>> {
307 let mut normals = facet_normals::<T>(cell);
308 for normal in normals.iter_mut() {
309 let size = normal.iter().map(|x| x.powi(2)).sum::<T>().sqrt();
310 for value in normal.iter_mut() {
311 *value /= size;
312 }
313 }
314 normals
315}
316
317pub fn entity_types(cell: ReferenceCellType) -> Vec<Vec<ReferenceCellType>> {
319 match cell {
320 ReferenceCellType::Point => vec![vec![ReferenceCellType::Point], vec![], vec![], vec![]],
321 ReferenceCellType::Interval => vec![
322 vec![ReferenceCellType::Point; 2],
323 vec![ReferenceCellType::Interval],
324 vec![],
325 vec![],
326 ],
327 ReferenceCellType::Triangle => vec![
328 vec![ReferenceCellType::Point; 3],
329 vec![ReferenceCellType::Interval; 3],
330 vec![ReferenceCellType::Triangle],
331 vec![],
332 ],
333 ReferenceCellType::Quadrilateral => vec![
334 vec![ReferenceCellType::Point; 4],
335 vec![ReferenceCellType::Interval; 4],
336 vec![ReferenceCellType::Quadrilateral],
337 vec![],
338 ],
339 ReferenceCellType::Tetrahedron => vec![
340 vec![ReferenceCellType::Point; 4],
341 vec![ReferenceCellType::Interval; 6],
342 vec![ReferenceCellType::Triangle; 4],
343 vec![ReferenceCellType::Tetrahedron],
344 ],
345 ReferenceCellType::Hexahedron => vec![
346 vec![ReferenceCellType::Point; 8],
347 vec![ReferenceCellType::Interval; 12],
348 vec![ReferenceCellType::Quadrilateral; 6],
349 vec![ReferenceCellType::Hexahedron],
350 ],
351 ReferenceCellType::Prism => vec![
352 vec![ReferenceCellType::Point; 6],
353 vec![ReferenceCellType::Interval; 9],
354 vec![
355 ReferenceCellType::Triangle,
356 ReferenceCellType::Quadrilateral,
357 ReferenceCellType::Quadrilateral,
358 ReferenceCellType::Quadrilateral,
359 ReferenceCellType::Triangle,
360 ],
361 vec![ReferenceCellType::Prism],
362 ],
363 ReferenceCellType::Pyramid => vec![
364 vec![ReferenceCellType::Point; 5],
365 vec![ReferenceCellType::Interval; 8],
366 vec![
367 ReferenceCellType::Quadrilateral,
368 ReferenceCellType::Triangle,
369 ReferenceCellType::Triangle,
370 ReferenceCellType::Triangle,
371 ReferenceCellType::Triangle,
372 ],
373 vec![ReferenceCellType::Pyramid],
374 ],
375 }
376}
377
378pub fn entity_indices(cell: ReferenceCellType) -> Vec<Vec<usize>> {
380 match cell {
381 ReferenceCellType::Point => vec![vec![0], vec![], vec![], vec![]],
382 ReferenceCellType::Interval => vec![vec![0, 1], vec![0], vec![], vec![]],
383 ReferenceCellType::Triangle => vec![vec![0, 1, 2], vec![0, 1, 2], vec![0], vec![]],
384 ReferenceCellType::Quadrilateral => {
385 vec![vec![0, 1, 2, 3], vec![0, 1, 2, 3], vec![0], vec![]]
386 }
387 ReferenceCellType::Tetrahedron => vec![
388 vec![0, 1, 2, 3],
389 vec![0, 1, 2, 3, 4, 5],
390 vec![0, 1, 2, 3],
391 vec![0],
392 ],
393 ReferenceCellType::Hexahedron => vec![
394 vec![0, 1, 2, 3, 4, 5, 6, 7],
395 vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
396 vec![0, 1, 2, 3, 4, 5],
397 vec![0],
398 ],
399 ReferenceCellType::Prism => vec![
400 vec![0, 1, 2, 3, 4, 5],
401 vec![0, 1, 2, 3, 4, 5, 6, 7, 8],
402 vec![0, 0, 1, 2, 1],
403 vec![0],
404 ],
405 ReferenceCellType::Pyramid => vec![
406 vec![0, 1, 2, 3, 4],
407 vec![0, 1, 2, 3, 4, 5, 6, 7],
408 vec![0, 0, 1, 2, 3],
409 vec![0],
410 ],
411 }
412}
413
414pub fn entity_counts(cell: ReferenceCellType) -> Vec<usize> {
416 match cell {
417 ReferenceCellType::Point => vec![1, 0, 0, 0],
418 ReferenceCellType::Interval => vec![2, 1, 0, 0],
419 ReferenceCellType::Triangle => vec![3, 3, 1, 0],
420 ReferenceCellType::Quadrilateral => vec![4, 4, 1, 0],
421 ReferenceCellType::Tetrahedron => vec![4, 6, 4, 1],
422 ReferenceCellType::Hexahedron => vec![8, 12, 6, 1],
423 ReferenceCellType::Prism => vec![6, 9, 5, 1],
424 ReferenceCellType::Pyramid => vec![5, 8, 5, 1],
425 }
426}
427
428pub fn connectivity(cell: ReferenceCellType) -> Vec<Vec<Vec<Vec<usize>>>> {
432 match cell {
433 ReferenceCellType::Point => vec![vec![vec![vec![0]]]],
434 ReferenceCellType::Interval => vec![
435 vec![vec![vec![0], vec![0]], vec![vec![1], vec![0]]],
436 vec![vec![vec![0, 1], vec![0]]],
437 ],
438 ReferenceCellType::Triangle => vec![
439 vec![
440 vec![vec![0], vec![1, 2], vec![0]],
441 vec![vec![1], vec![0, 2], vec![0]],
442 vec![vec![2], vec![0, 1], vec![0]],
443 ],
444 vec![
445 vec![vec![1, 2], vec![0], vec![0]],
446 vec![vec![0, 2], vec![1], vec![0]],
447 vec![vec![0, 1], vec![2], vec![0]],
448 ],
449 vec![vec![vec![0, 1, 2], vec![0, 1, 2], vec![0]]],
450 ],
451 ReferenceCellType::Quadrilateral => vec![
452 vec![
453 vec![vec![0], vec![0, 1], vec![0]],
454 vec![vec![1], vec![0, 2], vec![0]],
455 vec![vec![2], vec![1, 3], vec![0]],
456 vec![vec![3], vec![2, 3], vec![0]],
457 ],
458 vec![
459 vec![vec![0, 1], vec![0], vec![0]],
460 vec![vec![0, 2], vec![1], vec![0]],
461 vec![vec![1, 3], vec![2], vec![0]],
462 vec![vec![2, 3], vec![3], vec![0]],
463 ],
464 vec![vec![vec![0, 1, 2, 3], vec![0, 1, 2, 3], vec![0]]],
465 ],
466 ReferenceCellType::Tetrahedron => vec![
467 vec![
468 vec![vec![0], vec![3, 4, 5], vec![1, 2, 3], vec![0]],
469 vec![vec![1], vec![1, 2, 5], vec![0, 2, 3], vec![0]],
470 vec![vec![2], vec![0, 2, 4], vec![0, 1, 3], vec![0]],
471 vec![vec![3], vec![0, 1, 3], vec![0, 1, 2], vec![0]],
472 ],
473 vec![
474 vec![vec![2, 3], vec![0], vec![0, 1], vec![0]],
475 vec![vec![1, 3], vec![1], vec![0, 2], vec![0]],
476 vec![vec![1, 2], vec![2], vec![0, 3], vec![0]],
477 vec![vec![0, 3], vec![3], vec![1, 2], vec![0]],
478 vec![vec![0, 2], vec![4], vec![1, 3], vec![0]],
479 vec![vec![0, 1], vec![5], vec![2, 3], vec![0]],
480 ],
481 vec![
482 vec![vec![1, 2, 3], vec![0, 1, 2], vec![0], vec![0]],
483 vec![vec![0, 2, 3], vec![0, 3, 4], vec![1], vec![0]],
484 vec![vec![0, 1, 3], vec![1, 3, 5], vec![2], vec![0]],
485 vec![vec![0, 1, 2], vec![2, 4, 5], vec![3], vec![0]],
486 ],
487 vec![vec![
488 vec![0, 1, 2, 3],
489 vec![0, 1, 2, 3, 4, 5],
490 vec![0, 1, 2, 3],
491 vec![0],
492 ]],
493 ],
494 ReferenceCellType::Hexahedron => vec![
495 vec![
496 vec![vec![0], vec![0, 1, 2], vec![0, 1, 2], vec![0]],
497 vec![vec![1], vec![0, 3, 4], vec![0, 1, 3], vec![0]],
498 vec![vec![2], vec![1, 5, 6], vec![0, 2, 4], vec![0]],
499 vec![vec![3], vec![3, 5, 7], vec![0, 3, 4], vec![0]],
500 vec![vec![4], vec![2, 8, 9], vec![1, 2, 5], vec![0]],
501 vec![vec![5], vec![4, 8, 10], vec![1, 3, 5], vec![0]],
502 vec![vec![6], vec![6, 9, 11], vec![2, 4, 5], vec![0]],
503 vec![vec![7], vec![7, 10, 11], vec![3, 4, 5], vec![0]],
504 ],
505 vec![
506 vec![vec![0, 1], vec![0], vec![0, 1], vec![0]],
507 vec![vec![0, 2], vec![1], vec![0, 2], vec![0]],
508 vec![vec![0, 4], vec![2], vec![1, 2], vec![0]],
509 vec![vec![1, 3], vec![3], vec![0, 3], vec![0]],
510 vec![vec![1, 5], vec![4], vec![1, 3], vec![0]],
511 vec![vec![2, 3], vec![5], vec![0, 4], vec![0]],
512 vec![vec![2, 6], vec![6], vec![2, 4], vec![0]],
513 vec![vec![3, 7], vec![7], vec![3, 4], vec![0]],
514 vec![vec![4, 5], vec![8], vec![1, 5], vec![0]],
515 vec![vec![4, 6], vec![9], vec![2, 5], vec![0]],
516 vec![vec![5, 7], vec![10], vec![3, 5], vec![0]],
517 vec![vec![6, 7], vec![11], vec![4, 5], vec![0]],
518 ],
519 vec![
520 vec![vec![0, 1, 2, 3], vec![0, 1, 3, 5], vec![0], vec![0]],
521 vec![vec![0, 1, 4, 5], vec![0, 2, 4, 8], vec![1], vec![0]],
522 vec![vec![0, 2, 4, 6], vec![1, 2, 6, 9], vec![2], vec![0]],
523 vec![vec![1, 3, 5, 7], vec![3, 4, 7, 10], vec![3], vec![0]],
524 vec![vec![2, 3, 6, 7], vec![5, 6, 7, 11], vec![4], vec![0]],
525 vec![vec![4, 5, 6, 7], vec![8, 9, 10, 11], vec![5], vec![0]],
526 ],
527 vec![vec![
528 vec![0, 1, 2, 3, 4, 5, 6, 7],
529 vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
530 vec![0, 1, 2, 3, 4, 5],
531 vec![0],
532 ]],
533 ],
534 ReferenceCellType::Prism => vec![
535 vec![
536 vec![vec![0], vec![0, 1, 2], vec![0, 1, 2], vec![0]],
537 vec![vec![1], vec![0, 3, 4], vec![0, 1, 3], vec![0]],
538 vec![vec![2], vec![1, 3, 5], vec![0, 2, 3], vec![0]],
539 vec![vec![3], vec![2, 6, 7], vec![1, 2, 4], vec![0]],
540 vec![vec![4], vec![4, 6, 8], vec![1, 3, 4], vec![0]],
541 vec![vec![5], vec![5, 7, 8], vec![2, 3, 4], vec![0]],
542 ],
543 vec![
544 vec![vec![0, 1], vec![0], vec![0, 1], vec![0]],
545 vec![vec![0, 2], vec![1], vec![0, 2], vec![0]],
546 vec![vec![0, 3], vec![2], vec![1, 2], vec![0]],
547 vec![vec![1, 2], vec![3], vec![0, 3], vec![0]],
548 vec![vec![1, 4], vec![4], vec![1, 3], vec![0]],
549 vec![vec![2, 5], vec![5], vec![2, 3], vec![0]],
550 vec![vec![3, 4], vec![6], vec![1, 4], vec![0]],
551 vec![vec![3, 5], vec![7], vec![2, 4], vec![0]],
552 vec![vec![4, 5], vec![8], vec![3, 4], vec![0]],
553 ],
554 vec![
555 vec![vec![0, 1, 2], vec![0, 1, 3], vec![0], vec![0]],
556 vec![vec![0, 1, 3, 4], vec![0, 2, 4, 6], vec![1], vec![0]],
557 vec![vec![0, 2, 3, 5], vec![1, 2, 5, 7], vec![2], vec![0]],
558 vec![vec![1, 2, 4, 5], vec![3, 4, 5, 8], vec![3], vec![0]],
559 vec![vec![3, 4, 5], vec![6, 7, 8], vec![4], vec![0]],
560 ],
561 vec![vec![
562 vec![0, 1, 2, 3, 4, 5],
563 vec![0, 1, 2, 3, 4, 5, 6, 7, 8],
564 vec![0, 1, 2, 3, 4],
565 vec![0],
566 ]],
567 ],
568 ReferenceCellType::Pyramid => vec![
569 vec![
570 vec![vec![0], vec![0, 1, 2], vec![0, 1, 2], vec![0]],
571 vec![vec![1], vec![0, 3, 4], vec![0, 1, 3], vec![0]],
572 vec![vec![2], vec![1, 5, 6], vec![0, 2, 4], vec![0]],
573 vec![vec![3], vec![3, 5, 7], vec![0, 3, 4], vec![0]],
574 vec![vec![4], vec![2, 4, 6, 7], vec![1, 2, 3, 4], vec![0]],
575 ],
576 vec![
577 vec![vec![0, 1], vec![0], vec![0, 1], vec![0]],
578 vec![vec![0, 2], vec![1], vec![0, 2], vec![0]],
579 vec![vec![0, 4], vec![2], vec![1, 2], vec![0]],
580 vec![vec![1, 3], vec![3], vec![0, 3], vec![0]],
581 vec![vec![1, 4], vec![4], vec![1, 3], vec![0]],
582 vec![vec![2, 3], vec![5], vec![0, 4], vec![0]],
583 vec![vec![2, 4], vec![6], vec![2, 4], vec![0]],
584 vec![vec![3, 4], vec![7], vec![3, 4], vec![0]],
585 ],
586 vec![
587 vec![vec![0, 1, 2, 3], vec![0, 1, 3, 5], vec![0], vec![0]],
588 vec![vec![0, 1, 4], vec![0, 2, 4], vec![1], vec![0]],
589 vec![vec![0, 2, 4], vec![1, 2, 6], vec![2], vec![0]],
590 vec![vec![1, 3, 4], vec![3, 4, 7], vec![3], vec![0]],
591 vec![vec![2, 3, 4], vec![5, 6, 7], vec![4], vec![0]],
592 ],
593 vec![vec![
594 vec![0, 1, 2, 3, 4],
595 vec![0, 1, 2, 3, 4, 5, 6, 7],
596 vec![0, 1, 2, 3, 4],
597 vec![0],
598 ]],
599 ],
600 }
601}
602
603#[cfg(test)]
604mod test {
605 use super::*;
606 use approx::*;
607 use itertools::izip;
608 use paste::paste;
609
610 macro_rules! test_cell {
611 ($cell:ident) => {
612 paste! {
613
614 #[test]
615 fn [<test_ $cell:lower>]() {
616 let v = vertices::<f64>(ReferenceCellType::[<$cell>]);
617 let d = dim(ReferenceCellType::[<$cell>]);
618 let ec = entity_counts(ReferenceCellType::[<$cell>]);
619 let et = entity_types(ReferenceCellType::[<$cell>]);
620 let conn = connectivity(ReferenceCellType::[<$cell>]);
621 for i in 0..d+1 {
622 assert_eq!(ec[i], et[i].len());
623 assert_eq!(ec[i], conn[i].len());
624 }
625 assert_eq!(ec[0], v.len());
626 for i in v {
627 assert_eq!(i.len(), d);
628 }
629
630 for v_n in 0..ec[0] {
631 let v = &conn[0][v_n][0];
632 assert_eq!(v, &[v_n]);
633 }
634 for e_n in 0..ec[1] {
635 let vs = &conn[1][e_n][0];
636 assert_eq!(vs, &edges(ReferenceCellType::[<$cell>])[e_n]);
637 }
638 for f_n in 0..ec[2] {
639 let vs = &conn[2][f_n][0];
640 assert_eq!(vs, &faces(ReferenceCellType::[<$cell>])[f_n]);
641 }
642
643 for e_dim in 0..d {
644 for e_n in 0..ec[e_dim] {
645 let e_vertices = &conn[e_dim][e_n][0];
646 for c_dim in 0..d + 1 {
647 let connectivity = &conn[e_dim][e_n][c_dim];
648 if e_dim == c_dim {
649 assert_eq!(connectivity.len(), 1);
650 assert_eq!(connectivity[0], e_n)
651 } else {
652 for c_n in connectivity {
653 let c_vertices = &conn[c_dim][*c_n][0];
654 if e_dim < c_dim {
655 for i in e_vertices {
656 assert!(c_vertices.contains(&i));
657 }
658 } else {
659 for i in c_vertices {
660 assert!(e_vertices.contains(&i));
661 }
662 }
663 assert!(connectivity.contains(&c_n));
664 }
665 }
666 }
667 }
668 }
669 }
670 }
671 };
672 }
673
674 test_cell!(Interval);
675 test_cell!(Triangle);
676 test_cell!(Quadrilateral);
677 test_cell!(Tetrahedron);
678 test_cell!(Hexahedron);
679 test_cell!(Prism);
680 test_cell!(Pyramid);
681
682 macro_rules! test_facet_normals_2d {
683 ($cell:ident) => {
684 paste! {
685
686 #[test]
687 fn [<test_ $cell:lower _facet_normals>]() {
688 let v = vertices::<f64>(ReferenceCellType::[<$cell>]);
689 let ns = facet_normals::<f64>(ReferenceCellType::[<$cell>]);
690 let es = edges(ReferenceCellType::[<$cell>]);
691
692 for (e, n) in izip!(es, ns) {
693 let tangent = (0..2).map(|i| v[e[1]][i] - v[e[0]][i]).collect::<Vec<_>>();
694 assert_relative_eq!(n[0], -tangent[1]);
695 assert_relative_eq!(n[1], tangent[0]);
696 }
697 }
698 }
699 };
700 }
701
702 fn cross<T: RlstScalar>(a: &[T], b: &[T]) -> Vec<T> {
703 assert_eq!(a.len(), 3);
704 assert_eq!(b.len(), 3);
705 vec![
706 a[1] * b[2] - a[2] * b[1],
707 a[2] * b[0] - a[0] * b[2],
708 a[0] * b[1] - a[1] * b[0],
709 ]
710 }
711
712 macro_rules! test_facet_normals_3d {
713 ($cell:ident) => {
714 paste! {
715
716 #[test]
717 fn [<test_ $cell:lower _facet_normals>]() {
718 let v = vertices::<f64>(ReferenceCellType::[<$cell>]);
719 let ns = facet_normals::<f64>(ReferenceCellType::[<$cell>]);
720 let fs = faces(ReferenceCellType::[<$cell>]);
721
722 for (f, n) in izip!(fs, ns) {
723 let tangent0 = (0..3).map(|i| v[f[1]][i] - v[f[0]][i]).collect::<Vec<_>>();
724 let tangent1 = (0..3).map(|i| v[f[2]][i] - v[f[0]][i]).collect::<Vec<_>>();
725 for (i, j) in izip!(n, cross(&tangent0, &tangent1)) {
726 assert_relative_eq!(i, j);
727 }
728 }
729 }
730 }
731 };
732 }
733
734 test_facet_normals_2d!(Triangle);
735 test_facet_normals_2d!(Quadrilateral);
736 test_facet_normals_3d!(Tetrahedron);
737 test_facet_normals_3d!(Hexahedron);
738 test_facet_normals_3d!(Prism);
739 test_facet_normals_3d!(Pyramid);
740}