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

1pub mod elastic;
2pub mod linear;
3
4use crate::{
5    fem::block::element::{
6        ElementNodalCoordinates, ElementNodalEitherCoordinates, FiniteElement,
7        ShapeFunctionsAtIntegrationPoints, surface::SurfaceFiniteElement,
8    },
9    math::{ScalarList, Tensor},
10    mechanics::{CurrentCoordinate, NormalGradients},
11};
12use std::fmt::{self, Debug, Formatter};
13
14pub type Separation = CurrentCoordinate;
15pub type Separations<const P: usize> = ElementNodalCoordinates<P>;
16
17const M: usize = 2;
18
19pub struct CohesiveElement<const G: usize, const N: usize, const O: usize> {
20    integration_weights: ScalarList<G>,
21}
22
23impl<const G: usize, const N: usize, const O: usize> Debug for CohesiveElement<G, N, O> {
24    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
25        let element = match (G, N, O) {
26            (3, 6, 1) => "LinearCohesiveWedge",
27            (4, 8, 1) => "LinearCohesiveHexahedron",
28            _ => panic!(),
29        };
30        write!(f, "{element} {{ G: {G}, N: {N} }}",)
31    }
32}
33
34impl<const G: usize, const N: usize, const O: usize, const P: usize> SurfaceFiniteElement<G, N, P>
35    for CohesiveElement<G, N, O>
36where
37    Self: FiniteElement<G, M, N, P>,
38{
39}
40
41pub trait CohesiveFiniteElement<const G: usize, const N: usize, const P: usize>
42where
43    Self: SurfaceFiniteElement<G, N, P>,
44{
45    fn nodal_mid_surface<const I: usize>(
46        nodal_coordinates: &ElementNodalEitherCoordinates<I, N>,
47    ) -> ElementNodalEitherCoordinates<I, P>;
48    fn nodal_separations(nodal_coordinates: &ElementNodalCoordinates<N>) -> Separations<P>;
49    fn normal_gradients_full(
50        nodal_mid_surface: &ElementNodalCoordinates<P>,
51    ) -> NormalGradients<N, G>;
52    fn separations(nodal_coordinates: &ElementNodalCoordinates<N>) -> Separations<G> {
53        Self::shape_functions_at_integration_points()
54            .into_iter()
55            .map(|shape_functions| {
56                Self::nodal_separations(nodal_coordinates)
57                    .into_iter()
58                    .zip(shape_functions.iter())
59                    .map(|(nodal_separation, shape_function)| nodal_separation * shape_function)
60                    .sum()
61            })
62            .collect()
63    }
64    fn signed_shape_functions() -> ShapeFunctionsAtIntegrationPoints<G, N> {
65        Self::shape_functions_at_integration_points()
66            .into_iter()
67            .map(|shape_functions| {
68                shape_functions
69                    .iter()
70                    .chain(shape_functions.iter())
71                    .zip(Self::signs())
72                    .map(|(shape_function, sign)| shape_function * sign)
73                    .collect()
74            })
75            .collect()
76    }
77    fn signs() -> ScalarList<N>;
78}