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

1#[cfg(test)]
2mod test;
3
4use super::*;
5use crate::{
6    math::{tensor_rank_0_list, tensor_rank_1, tensor_rank_1_list, tensor_rank_1_list_2d},
7    mechanics::Scalar,
8};
9
10const G: usize = 1;
11const M: usize = 3;
12const N: usize = 4;
13const P: usize = G;
14
15#[cfg(test)]
16const Q: usize = N;
17
18pub type Tetrahedron<'a, C> = Element<'a, C, G, N>;
19
20impl<'a, C> FiniteElement<'a, C, G, N> for Tetrahedron<'a, C> {
21    fn new(
22        constitutive_model: &'a C,
23        reference_nodal_coordinates: ReferenceNodalCoordinates<N>,
24    ) -> Self {
25        let (gradient_vectors, integration_weights) = Self::initialize(reference_nodal_coordinates);
26        Self {
27            constitutive_model,
28            gradient_vectors,
29            integration_weights,
30        }
31    }
32    fn reference() -> ReferenceNodalCoordinates<N> {
33        tensor_rank_1_list([
34            tensor_rank_1([0.0, 0.0, 0.0]),
35            tensor_rank_1([1.0, 0.0, 0.0]),
36            tensor_rank_1([0.0, 1.0, 0.0]),
37            tensor_rank_1([0.0, 0.0, 1.0]),
38        ])
39    }
40    fn reset(&mut self) {
41        let (gradient_vectors, integration_weights) = Self::initialize(Self::reference());
42        self.gradient_vectors = gradient_vectors;
43        self.integration_weights = integration_weights;
44    }
45}
46
47impl<'a, C> Tetrahedron<'a, C> {
48    fn initialize(
49        reference_nodal_coordinates: ReferenceNodalCoordinates<N>,
50    ) -> (GradientVectors<G, N>, Scalars<G>) {
51        let standard_gradient_operator = &Self::standard_gradient_operators()[0];
52        let (operator, jacobian) = (reference_nodal_coordinates * standard_gradient_operator)
53            .inverse_transpose_and_determinant();
54        let gradient_vectors = tensor_rank_1_list_2d([operator * standard_gradient_operator]);
55        let integration_weights = tensor_rank_0_list([jacobian * Self::integration_weight()]);
56        (gradient_vectors, integration_weights)
57    }
58    const fn integration_weight() -> Scalar {
59        1.0 / 6.0
60    }
61    #[cfg(test)]
62    const fn shape_functions_at_integration_points() -> ShapeFunctionsAtIntegrationPoints<G, Q> {
63        tensor_rank_1_list([tensor_rank_1([0.25; Q])])
64    }
65    const fn standard_gradient_operators() -> StandardGradientOperators<M, N, P> {
66        tensor_rank_1_list_2d([tensor_rank_1_list([
67            tensor_rank_1([-1.0, -1.0, -1.0]),
68            tensor_rank_1([1.0, 0.0, 0.0]),
69            tensor_rank_1([0.0, 1.0, 0.0]),
70            tensor_rank_1([0.0, 0.0, 1.0]),
71        ])])
72    }
73}