conspire/domain/fem/block/element/linear/
mod.rs1mod 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;