conspire/domain/fem/block/element/linear/
mod.rs

1mod hexahedron;
2mod pyramid;
3mod tetrahedron;
4mod wedge;
5
6pub use hexahedron::Hexahedron;
7pub use pyramid::Pyramid;
8pub use tetrahedron::Tetrahedron;
9pub use wedge::Wedge;
10
11use crate::math::Scalar;
12
13const FRAC_1_SQRT_3: Scalar = 0.577_350_269_189_625_8;
14
15macro_rules! implement {
16    ($element:ident) => {
17        #[cfg(test)]
18        mod test;
19        #[cfg(test)]
20        use crate::fem::block::element::ShapeFunctionsAtIntegrationPoints;
21        use crate::{
22            fem::block::element::{
23                Element, ElementNodalReferenceCoordinates, FiniteElement, GradientVectors,
24                StandardGradientOperators,
25            },
26            math::{Scalar, Scalars},
27        };
28        const M: usize = 3;
29        const P: usize = G;
30        #[cfg(test)]
31        const Q: usize = N;
32        impl FiniteElement<G, N> for $element {
33            fn initialize(
34                reference_nodal_coordinates: ElementNodalReferenceCoordinates<N>,
35            ) -> (GradientVectors<G, N>, Scalars<G>) {
36                let gradient_vectors = Self::standard_gradient_operators()
37                    .into_iter()
38                    .map(|standard_gradient_operator| {
39                        (&reference_nodal_coordinates * &standard_gradient_operator)
40                            .inverse_transpose()
41                            * standard_gradient_operator
42                    })
43                    .collect();
44                let integration_weights = Self::standard_gradient_operators()
45                    .into_iter()
46                    .zip(Self::integration_weight())
47                    .map(|(standard_gradient_operator, integration_weight)| {
48                        (&reference_nodal_coordinates * standard_gradient_operator).determinant()
49                            * integration_weight
50                    })
51                    .collect();
52                (gradient_vectors, integration_weights)
53            }
54            fn reset(&mut self) {
55                let (gradient_vectors, integration_weights) = Self::initialize(Self::reference());
56                self.gradient_vectors = gradient_vectors;
57                self.integration_weights = integration_weights;
58            }
59        }
60        impl $element {
61            #[cfg(test)]
62            const fn shape_functions_at_integration_points()
63            -> ShapeFunctionsAtIntegrationPoints<G, Q> {
64                let mut g = 0;
65                let mut shape_functions = [[0.0; Q]; G];
66                let integration_points = Self::integration_points();
67                while g < G {
68                    shape_functions[g] = Self::shape_functions(integration_points[g]);
69                    g += 1;
70                }
71                ShapeFunctionsAtIntegrationPoints::<G, Q>::const_from(shape_functions)
72            }
73            const fn standard_gradient_operators() -> StandardGradientOperators<M, N, P> {
74                let mut g = 0;
75                let mut shape_functions_gradients = [[[0.0; M]; N]; G];
76                let integration_points = Self::integration_points();
77                while g < G {
78                    shape_functions_gradients[g] =
79                        Self::shape_functions_gradients(integration_points[g]);
80                    g += 1;
81                }
82                StandardGradientOperators::<M, N, P>::const_from(shape_functions_gradients)
83            }
84        }
85    };
86}
87pub(crate) use implement;