conspire/constitutive/cohesive/elastic/
mod.rs1use 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
13pub 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#[derive(Clone, Debug)]
86pub struct LinearElastic {
87 pub normal_stiffness: Scalar,
89 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}