conspire/constitutive/solid/elastic/
mod.rs1#![doc = include_str!("doc.md")]
6
7#[cfg(feature = "doc")]
8pub mod doc;
9
10#[cfg(test)]
11pub mod test;
12
13#[cfg(feature = "autodiff")]
14pub mod autodiff;
15
16pub mod internal_variables;
17
18mod almansi_hamel_eulerian;
19mod almansi_hamel_lagrangian;
20mod bazant_itskov_eulerian;
21mod bazant_itskov_lagrangian;
22mod hencky;
23mod saint_venant_kirchhoff;
24mod seth_hill_eulerian;
25mod seth_hill_lagrangian;
26
27pub use self::{
28 almansi_hamel_eulerian::AlmansiHamelEulerian, almansi_hamel_lagrangian::AlmansiHamelLagrangian,
29 bazant_itskov_eulerian::BazantItskovEulerian, bazant_itskov_lagrangian::BazantItskovLagrangian,
30 hencky::Hencky, saint_venant_kirchhoff::SaintVenantKirchhoff,
31 seth_hill_eulerian::SethHillEulerian, seth_hill_lagrangian::SethHillLagrangian,
32};
33
34use super::*;
35use crate::math::{
36 Matrix, Vector,
37 optimize::{EqualityConstraint, FirstOrderRootFinding, ZerothOrderRootFinding},
38};
39
40pub enum AppliedLoad {
42 UniaxialStress(Scalar),
44 BiaxialStress(Scalar, Scalar),
46}
47
48pub trait Elastic
50where
51 Self: Solid,
52{
53 fn cauchy_stress(
59 &self,
60 deformation_gradient: &DeformationGradient,
61 ) -> Result<CauchyStress, ConstitutiveError> {
62 Ok(deformation_gradient
63 * self.second_piola_kirchhoff_stress(deformation_gradient)?
64 * deformation_gradient.transpose()
65 / deformation_gradient.determinant())
66 }
67 fn cauchy_tangent_stiffness(
73 &self,
74 deformation_gradient: &DeformationGradient,
75 ) -> Result<CauchyTangentStiffness, ConstitutiveError> {
76 let deformation_gradient_inverse_transpose = deformation_gradient.inverse_transpose();
77 let cauchy_stress = self.cauchy_stress(deformation_gradient)?;
78 let some_stress = &cauchy_stress * &deformation_gradient_inverse_transpose;
79 Ok(self
80 .second_piola_kirchhoff_tangent_stiffness(deformation_gradient)?
81 .contract_first_second_with_second(deformation_gradient, deformation_gradient)
82 / deformation_gradient.determinant()
83 - CauchyTangentStiffness::dyad_ij_kl(
84 &cauchy_stress,
85 &deformation_gradient_inverse_transpose,
86 )
87 + CauchyTangentStiffness::dyad_il_kj(&some_stress, &IDENTITY)
88 + CauchyTangentStiffness::dyad_ik_jl(&IDENTITY, &some_stress))
89 }
90 fn first_piola_kirchhoff_stress(
96 &self,
97 deformation_gradient: &DeformationGradient,
98 ) -> Result<FirstPiolaKirchhoffStress, ConstitutiveError> {
99 Ok(self.cauchy_stress(deformation_gradient)?
100 * deformation_gradient.inverse_transpose()
101 * deformation_gradient.determinant())
102 }
103 fn first_piola_kirchhoff_tangent_stiffness(
109 &self,
110 deformation_gradient: &DeformationGradient,
111 ) -> Result<FirstPiolaKirchhoffTangentStiffness, ConstitutiveError> {
112 let deformation_gradient_inverse_transpose = deformation_gradient.inverse_transpose();
113 let first_piola_kirchhoff_stress =
114 self.first_piola_kirchhoff_stress(deformation_gradient)?;
115 Ok(self
116 .cauchy_tangent_stiffness(deformation_gradient)?
117 .contract_second_with_first(&deformation_gradient_inverse_transpose)
118 * deformation_gradient.determinant()
119 + FirstPiolaKirchhoffTangentStiffness::dyad_ij_kl(
120 &first_piola_kirchhoff_stress,
121 &deformation_gradient_inverse_transpose,
122 )
123 - FirstPiolaKirchhoffTangentStiffness::dyad_il_kj(
124 &first_piola_kirchhoff_stress,
125 &deformation_gradient_inverse_transpose,
126 ))
127 }
128 fn second_piola_kirchhoff_stress(
134 &self,
135 deformation_gradient: &DeformationGradient,
136 ) -> Result<SecondPiolaKirchhoffStress, ConstitutiveError> {
137 Ok(deformation_gradient.inverse()
138 * self.first_piola_kirchhoff_stress(deformation_gradient)?)
139 }
140 fn second_piola_kirchhoff_tangent_stiffness(
146 &self,
147 deformation_gradient: &DeformationGradient,
148 ) -> Result<SecondPiolaKirchhoffTangentStiffness, ConstitutiveError> {
149 let deformation_gradient_inverse_transpose = deformation_gradient.inverse_transpose();
150 let deformation_gradient_inverse = deformation_gradient_inverse_transpose.transpose();
151 let second_piola_kirchhoff_stress =
152 self.second_piola_kirchhoff_stress(deformation_gradient)?;
153 Ok(self
154 .cauchy_tangent_stiffness(deformation_gradient)?
155 .contract_first_second_with_second(
156 &deformation_gradient_inverse,
157 &deformation_gradient_inverse,
158 )
159 * deformation_gradient.determinant()
160 + SecondPiolaKirchhoffTangentStiffness::dyad_ij_kl(
161 &second_piola_kirchhoff_stress,
162 &deformation_gradient_inverse_transpose,
163 )
164 - SecondPiolaKirchhoffTangentStiffness::dyad_il_kj(
165 &second_piola_kirchhoff_stress,
166 &deformation_gradient_inverse_transpose,
167 )
168 - SecondPiolaKirchhoffTangentStiffness::dyad_ik_jl(
169 &deformation_gradient_inverse,
170 &second_piola_kirchhoff_stress,
171 ))
172 }
173}
174
175pub trait ZerothOrderRoot {
177 fn root(
183 &self,
184 applied_load: AppliedLoad,
185 solver: impl ZerothOrderRootFinding<FirstPiolaKirchhoffStress, DeformationGradient>,
186 ) -> Result<DeformationGradient, ConstitutiveError>;
187}
188
189pub trait FirstOrderRoot {
191 fn root(
197 &self,
198 applied_load: AppliedLoad,
199 solver: impl FirstOrderRootFinding<
200 FirstPiolaKirchhoffStress,
201 FirstPiolaKirchhoffTangentStiffness,
202 DeformationGradient,
203 >,
204 ) -> Result<DeformationGradient, ConstitutiveError>;
205}
206
207impl<T> ZerothOrderRoot for T
208where
209 T: Elastic,
210{
211 fn root(
212 &self,
213 applied_load: AppliedLoad,
214 solver: impl ZerothOrderRootFinding<FirstPiolaKirchhoffStress, DeformationGradient>,
215 ) -> Result<DeformationGradient, ConstitutiveError> {
216 let (matrix, vector) = bcs(applied_load);
217 solver
218 .root(
219 |deformation_gradient: &DeformationGradient| {
220 Ok(self.first_piola_kirchhoff_stress(deformation_gradient)?)
221 },
222 DeformationGradient::identity(),
223 EqualityConstraint::Linear(matrix, vector),
224 )
225 .map_err(|error| ConstitutiveError::upstream(error, self))
226 }
227}
228
229impl<T> FirstOrderRoot for T
230where
231 T: Elastic,
232{
233 fn root(
234 &self,
235 applied_load: AppliedLoad,
236 solver: impl FirstOrderRootFinding<
237 FirstPiolaKirchhoffStress,
238 FirstPiolaKirchhoffTangentStiffness,
239 DeformationGradient,
240 >,
241 ) -> Result<DeformationGradient, ConstitutiveError> {
242 let (matrix, vector) = bcs(applied_load);
243 solver
244 .root(
245 |deformation_gradient: &DeformationGradient| {
246 Ok(self.first_piola_kirchhoff_stress(deformation_gradient)?)
247 },
248 |deformation_gradient: &DeformationGradient| {
249 Ok(self.first_piola_kirchhoff_tangent_stiffness(deformation_gradient)?)
250 },
251 DeformationGradient::identity(),
252 EqualityConstraint::Linear(matrix, vector),
253 None,
254 )
255 .map_err(|error| ConstitutiveError::upstream(error, self))
256 }
257}
258
259#[doc(hidden)]
260pub fn bcs(applied_load: AppliedLoad) -> (Matrix, Vector) {
261 match applied_load {
262 AppliedLoad::UniaxialStress(deformation_gradient_11) => {
263 let mut matrix = Matrix::zero(4, 9);
264 let mut vector = Vector::zero(4);
265 matrix[0][0] = 1.0;
266 matrix[1][1] = 1.0;
267 matrix[2][2] = 1.0;
268 matrix[3][5] = 1.0;
269 vector[0] = deformation_gradient_11;
270 (matrix, vector)
271 }
272 AppliedLoad::BiaxialStress(deformation_gradient_11, deformation_gradient_22) => {
273 let mut matrix = Matrix::zero(5, 9);
274 let mut vector = Vector::zero(5);
275 matrix[0][0] = 1.0;
276 matrix[1][1] = 1.0;
277 matrix[2][2] = 1.0;
278 matrix[3][5] = 1.0;
279 matrix[4][4] = 1.0;
280 vector[0] = deformation_gradient_11;
281 vector[4] = deformation_gradient_22;
282 (matrix, vector)
283 }
284 }
285}