Skip to main content

conspire/domain/fem/block/element/cohesive/linear/
mod.rs

1mod hexahedron;
2mod wedge;
3
4pub use hexahedron::Hexahedron;
5pub use wedge::Wedge;
6
7use crate::{
8    fem::block::element::{
9        ElementNodalCoordinates, ElementNodalEitherCoordinates, ElementNodalReferenceCoordinates,
10        FiniteElement,
11        cohesive::{CohesiveElement, Separations},
12        surface::SurfaceFiniteElement,
13    },
14    math::{CrossProduct, ScalarList, Tensor},
15    mechanics::NormalGradients,
16    units::Area,
17};
18use std::iter::repeat_n;
19
20pub type LinearCohesiveElement<const G: usize, const N: usize> = CohesiveElement<G, N, 1>;
21
22pub trait LinearCohesiveFiniteElement<const G: usize, const N: usize, const P: usize>
23where
24    Self: FiniteElement<G, 2, N, P, Area> + SurfaceFiniteElement<G, N, P, Area>,
25{
26    fn from_linear(
27        reference_nodal_coordinates: ElementNodalReferenceCoordinates<N>,
28    ) -> LinearCohesiveElement<G, N> {
29        let integration_weights = Self::bases(&Self::nodal_mid_surface_linear(
30            &reference_nodal_coordinates,
31        ))
32        .into_iter()
33        .zip(Self::parametric_weights())
34        .map(|(reference_basis, parametric_weight)| {
35            reference_basis[0].cross(&reference_basis[1]).norm() * parametric_weight
36        })
37        .collect();
38        LinearCohesiveElement {
39            integration_weights,
40        }
41    }
42    fn nodal_mid_surface_linear<I>(
43        nodal_coordinates: &ElementNodalEitherCoordinates<I, N>,
44    ) -> ElementNodalEitherCoordinates<I, P> {
45        nodal_coordinates
46            .iter()
47            .take(P)
48            .zip(nodal_coordinates.iter().skip(P))
49            .map(|(coordinates_bottom, coordinates_top)| {
50                (coordinates_top + coordinates_bottom) * 0.5
51            })
52            .collect()
53    }
54    fn nodal_separations_linear(nodal_coordinates: &ElementNodalCoordinates<N>) -> Separations<P> {
55        nodal_coordinates
56            .iter()
57            .take(P)
58            .zip(nodal_coordinates.iter().skip(P))
59            .map(|(coordinates_bottom, coordinates_top)| coordinates_top - coordinates_bottom)
60            .collect()
61    }
62    fn normal_gradients_full_linear(
63        nodal_mid_surface: &ElementNodalCoordinates<P>,
64    ) -> NormalGradients<N, G> {
65        Self::normal_gradients(nodal_mid_surface)
66            .into_iter()
67            .map(|normal_gradient| {
68                normal_gradient
69                    .iter()
70                    .chain(normal_gradient.iter())
71                    .cloned()
72                    .collect()
73            })
74            .collect()
75    }
76    fn signs_linear() -> ScalarList<N> {
77        repeat_n(-1.0, P).chain(repeat_n(1.0, P)).collect()
78    }
79}