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

1#[cfg(test)]
2mod test;
3
4use super::*;
5use crate::{
6    constitutive::{Constitutive, Parameters},
7    math::{tensor_rank_0_list, tensor_rank_1, tensor_rank_1_list, tensor_rank_1_list_2d},
8    mechanics::Scalar,
9};
10use std::array::from_fn;
11
12const G: usize = 1;
13const M: usize = 3;
14const N: usize = 4;
15const P: usize = 1;
16
17#[cfg(test)]
18const Q: usize = 4;
19
20pub type Tetrahedron<C> = Element<C, G, N>;
21
22impl<C, Y> FiniteElement<C, G, N, Y> for Tetrahedron<C>
23where
24    C: Constitutive<Y>,
25    Y: Parameters,
26{
27    fn new(
28        constitutive_model_parameters: Y,
29        reference_nodal_coordinates: ReferenceNodalCoordinates<N>,
30    ) -> Self {
31        let standard_gradient_operator = &Self::standard_gradient_operators()[0];
32        let (operator, jacobian) = (reference_nodal_coordinates * standard_gradient_operator)
33            .inverse_transpose_and_determinant();
34        Self {
35            constitutive_models: from_fn(|_| <C>::new(constitutive_model_parameters)),
36            gradient_vectors: tensor_rank_1_list_2d([operator * standard_gradient_operator]),
37            integration_weights: tensor_rank_0_list([jacobian * Self::integration_weight()]),
38        }
39    }
40}
41
42impl<C> Tetrahedron<C> {
43    const fn integration_weight() -> Scalar {
44        1.0 / 6.0
45    }
46    #[cfg(test)]
47    const fn shape_functions_at_integration_points() -> ShapeFunctionsAtIntegrationPoints<G, Q> {
48        tensor_rank_1_list([tensor_rank_1([0.25; Q])])
49    }
50    const fn standard_gradient_operators() -> StandardGradientOperators<M, N, P> {
51        tensor_rank_1_list_2d([tensor_rank_1_list([
52            tensor_rank_1([-1.0, -1.0, -1.0]),
53            tensor_rank_1([1.0, 0.0, 0.0]),
54            tensor_rank_1([0.0, 1.0, 0.0]),
55            tensor_rank_1([0.0, 0.0, 1.0]),
56        ])])
57    }
58}