Skip to main content

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