conspire/constitutive/cohesive/elastic/
mod.rs

1//! Elastic cohesive constitutive models.
2
3use crate::{
4    constitutive::{Constitutive, ConstitutiveError, cohesive::Cohesive},
5    math::{Tensor, TensorArray, TensorRank1, TensorRank2, TensorRank2List},
6    mechanics::{Normal, Scalar, Separation, Stiffness, Traction},
7};
8
9pub type Tractions = TensorRank1<2, 8>;
10pub type Stiffnesses = TensorRank2<2, 8, 8>;
11pub type StiffnessCohesive = TensorRank2List<3, 1, 1, 2>;
12
13/// Required methods for elastic cohesive constitutive models.
14pub trait Elastic
15where
16    Self: Cohesive,
17{
18    fn traction(
19        &self,
20        separation: Separation,
21        normal: Normal,
22    ) -> Result<Traction, ConstitutiveError> {
23        let normal_component = &separation * &normal;
24        let normal_separation = &normal * normal_component;
25        let tangential_separation = separation - normal_separation;
26        let tangential_component = tangential_separation.norm();
27        let [normal_traction, tangential_traction] = self
28            .tractions(normal_component, tangential_component)?
29            .into();
30        if tangential_component > 0.0 {
31            Ok(normal * normal_traction
32                + (tangential_separation / tangential_component) * tangential_traction)
33        } else {
34            Ok(normal * normal_traction)
35        }
36    }
37    fn tractions(
38        &self,
39        normal_separation: Scalar,
40        tangential_separation: Scalar,
41    ) -> Result<Tractions, ConstitutiveError>;
42    fn stiffness(
43        &self,
44        separation: Separation,
45        normal: Normal,
46    ) -> Result<StiffnessCohesive, ConstitutiveError> {
47        let normal_component = &separation * &normal;
48        let normal_separation = &normal * normal_component;
49        let tangential_separation = &separation - normal_separation;
50        let tangential_component = tangential_separation.norm();
51        let [normal_traction, tangential_traction] = self
52            .tractions(normal_component, tangential_component)?
53            .into();
54        let [[k_nn, _], [_, k_tt]] = self
55            .stiffnesses(normal_component, tangential_component)?
56            .into();
57        let (tangent, ratio, q_t) = if tangential_component > 0.0 {
58            (
59                tangential_separation / tangential_component,
60                normal_component / tangential_component,
61                tangential_traction / tangential_component,
62            )
63        } else {
64            (Traction::zero(), 0.0, k_tt)
65        };
66        let nn = Stiffness::from((&normal, &normal));
67        let nu = Stiffness::from((&normal, &separation));
68        let tt = Stiffness::from((&tangent, &tangent));
69        let tu = Stiffness::from((&tangent, &separation));
70        let identity = Stiffness::identity();
71        let stiffness_u = nn * (k_nn - q_t) + tt * (k_tt - q_t) + &identity * q_t;
72        let stiffness_n = nu * (k_nn - q_t)
73            + identity * (normal_traction - ratio * tangential_traction)
74            - tu * ((k_tt - q_t) * ratio);
75        Ok([stiffness_u, stiffness_n].into())
76    }
77    fn stiffnesses(
78        &self,
79        normal_separation: Scalar,
80        tangential_separation: Scalar,
81    ) -> Result<Stiffnesses, ConstitutiveError>;
82}
83
84/// The linear elastic cohesive constitutive model.
85#[derive(Clone, Debug)]
86pub struct LinearElastic {
87    /// The normal stiffness $`k_n`$.
88    pub normal_stiffness: Scalar,
89    /// The tangential stiffness $`k_t`$.
90    pub tangential_stiffness: Scalar,
91}
92
93impl Constitutive for LinearElastic {}
94
95impl Cohesive for LinearElastic {}
96
97impl Elastic for LinearElastic {
98    fn tractions(
99        &self,
100        normal_separation: Scalar,
101        tangential_separation: Scalar,
102    ) -> Result<Tractions, ConstitutiveError> {
103        Ok([
104            normal_separation * self.normal_stiffness,
105            tangential_separation * self.tangential_stiffness,
106        ]
107        .into())
108    }
109    fn stiffnesses(
110        &self,
111        _normal_separation: Scalar,
112        _tangential_separation: Scalar,
113    ) -> Result<Stiffnesses, ConstitutiveError> {
114        Ok([
115            [self.normal_stiffness, 0.0],
116            [0.0, self.tangential_stiffness],
117        ]
118        .into())
119    }
120}