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