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