conspire/fem/block/element/linear/tetrahedron/
mod.rs1#[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}