conspire/domain/fem/block/element/cohesive/linear/
mod.rs1mod 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}