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 = G;
16
17#[cfg(test)]
18const Q: usize = N;
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 (gradient_vectors, integration_weights) = Self::initialize(reference_nodal_coordinates);
32 Self {
33 constitutive_models: from_fn(|_| <C>::new(constitutive_model_parameters)),
34 gradient_vectors,
35 integration_weights,
36 }
37 }
38 fn reference() -> ReferenceNodalCoordinates<N> {
39 tensor_rank_1_list([
40 tensor_rank_1([0.0, 0.0, 0.0]),
41 tensor_rank_1([1.0, 0.0, 0.0]),
42 tensor_rank_1([0.0, 1.0, 0.0]),
43 tensor_rank_1([0.0, 0.0, 1.0]),
44 ])
45 }
46 fn reset(&mut self) {
47 let (gradient_vectors, integration_weights) = Self::initialize(Self::reference());
48 self.gradient_vectors = gradient_vectors;
49 self.integration_weights = integration_weights;
50 }
51}
52
53impl<C> Tetrahedron<C> {
54 fn initialize(
55 reference_nodal_coordinates: ReferenceNodalCoordinates<N>,
56 ) -> (GradientVectors<G, N>, Scalars<G>) {
57 let standard_gradient_operator = &Self::standard_gradient_operators()[0];
58 let (operator, jacobian) = (reference_nodal_coordinates * standard_gradient_operator)
59 .inverse_transpose_and_determinant();
60 let gradient_vectors = tensor_rank_1_list_2d([operator * standard_gradient_operator]);
61 let integration_weights = tensor_rank_0_list([jacobian * Self::integration_weight()]);
62 (gradient_vectors, integration_weights)
63 }
64 const fn integration_weight() -> Scalar {
65 1.0 / 6.0
66 }
67 #[cfg(test)]
68 const fn shape_functions_at_integration_points() -> ShapeFunctionsAtIntegrationPoints<G, Q> {
69 tensor_rank_1_list([tensor_rank_1([0.25; Q])])
70 }
71 const fn standard_gradient_operators() -> StandardGradientOperators<M, N, P> {
72 tensor_rank_1_list_2d([tensor_rank_1_list([
73 tensor_rank_1([-1.0, -1.0, -1.0]),
74 tensor_rank_1([1.0, 0.0, 0.0]),
75 tensor_rank_1([0.0, 1.0, 0.0]),
76 tensor_rank_1([0.0, 0.0, 1.0]),
77 ])])
78 }
79}