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