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
13mod almansi_hamel;
14mod hencky;
15mod saint_venant_kirchhoff;
16
17pub use self::{
18 almansi_hamel::AlmansiHamel, hencky::Hencky, saint_venant_kirchhoff::SaintVenantKirchhoff,
19};
20
21use super::*;
22use crate::math::{
23 Matrix, TensorVec, Vector,
24 optimize::{self, EqualityConstraint, OptimizeError},
25};
26
27pub enum AppliedLoad {
29 UniaxialStress(Scalar),
31 BiaxialStress(Scalar, Scalar),
33}
34
35pub trait Elastic
37where
38 Self: Solid,
39{
40 fn cauchy_stress(
46 &self,
47 deformation_gradient: &DeformationGradient,
48 ) -> Result<CauchyStress, ConstitutiveError> {
49 Ok(deformation_gradient
50 * self.second_piola_kirchhoff_stress(deformation_gradient)?
51 * deformation_gradient.transpose()
52 / deformation_gradient.determinant())
53 }
54 fn cauchy_tangent_stiffness(
60 &self,
61 deformation_gradient: &DeformationGradient,
62 ) -> Result<CauchyTangentStiffness, ConstitutiveError> {
63 let deformation_gradient_inverse_transpose = deformation_gradient.inverse_transpose();
64 let cauchy_stress = self.cauchy_stress(deformation_gradient)?;
65 let some_stress = &cauchy_stress * &deformation_gradient_inverse_transpose;
66 Ok(self
67 .second_piola_kirchhoff_tangent_stiffness(deformation_gradient)?
68 .contract_first_second_indices_with_second_indices_of(
69 deformation_gradient,
70 deformation_gradient,
71 )
72 / deformation_gradient.determinant()
73 - CauchyTangentStiffness::dyad_ij_kl(
74 &cauchy_stress,
75 &deformation_gradient_inverse_transpose,
76 )
77 + CauchyTangentStiffness::dyad_il_kj(&some_stress, &IDENTITY)
78 + CauchyTangentStiffness::dyad_ik_jl(&IDENTITY, &some_stress))
79 }
80 fn first_piola_kirchhoff_stress(
86 &self,
87 deformation_gradient: &DeformationGradient,
88 ) -> Result<FirstPiolaKirchhoffStress, ConstitutiveError> {
89 Ok(self.cauchy_stress(deformation_gradient)?
90 * deformation_gradient.inverse_transpose()
91 * deformation_gradient.determinant())
92 }
93 fn first_piola_kirchhoff_tangent_stiffness(
99 &self,
100 deformation_gradient: &DeformationGradient,
101 ) -> Result<FirstPiolaKirchhoffTangentStiffness, ConstitutiveError> {
102 let deformation_gradient_inverse_transpose = deformation_gradient.inverse_transpose();
103 let first_piola_kirchhoff_stress =
104 self.first_piola_kirchhoff_stress(deformation_gradient)?;
105 Ok(self
106 .cauchy_tangent_stiffness(deformation_gradient)?
107 .contract_second_index_with_first_index_of(&deformation_gradient_inverse_transpose)
108 * deformation_gradient.determinant()
109 + FirstPiolaKirchhoffTangentStiffness::dyad_ij_kl(
110 &first_piola_kirchhoff_stress,
111 &deformation_gradient_inverse_transpose,
112 )
113 - FirstPiolaKirchhoffTangentStiffness::dyad_il_kj(
114 &first_piola_kirchhoff_stress,
115 &deformation_gradient_inverse_transpose,
116 ))
117 }
118 fn second_piola_kirchhoff_stress(
124 &self,
125 deformation_gradient: &DeformationGradient,
126 ) -> Result<SecondPiolaKirchhoffStress, ConstitutiveError> {
127 Ok(deformation_gradient.inverse()
128 * self.cauchy_stress(deformation_gradient)?
129 * deformation_gradient.inverse_transpose()
130 * deformation_gradient.determinant())
131 }
132 fn second_piola_kirchhoff_tangent_stiffness(
138 &self,
139 deformation_gradient: &DeformationGradient,
140 ) -> Result<SecondPiolaKirchhoffTangentStiffness, ConstitutiveError> {
141 let deformation_gradient_inverse_transpose = deformation_gradient.inverse_transpose();
142 let deformation_gradient_inverse = deformation_gradient_inverse_transpose.transpose();
143 let second_piola_kirchhoff_stress =
144 self.second_piola_kirchhoff_stress(deformation_gradient)?;
145 Ok(self
146 .cauchy_tangent_stiffness(deformation_gradient)?
147 .contract_first_second_indices_with_second_indices_of(
148 &deformation_gradient_inverse,
149 &deformation_gradient_inverse,
150 )
151 * deformation_gradient.determinant()
152 + SecondPiolaKirchhoffTangentStiffness::dyad_ij_kl(
153 &second_piola_kirchhoff_stress,
154 &deformation_gradient_inverse_transpose,
155 )
156 - SecondPiolaKirchhoffTangentStiffness::dyad_il_kj(
157 &second_piola_kirchhoff_stress,
158 &deformation_gradient_inverse_transpose,
159 )
160 - SecondPiolaKirchhoffTangentStiffness::dyad_ik_jl(
161 &deformation_gradient_inverse,
162 &second_piola_kirchhoff_stress,
163 ))
164 }
165}
166
167pub trait ZerothOrderRoot {
169 fn root(
175 &self,
176 applied_load: AppliedLoad,
177 solver: impl optimize::ZerothOrderRootFinding<DeformationGradient>,
178 ) -> Result<DeformationGradient, OptimizeError>;
179}
180
181pub trait FirstOrderRoot {
183 fn root(
189 &self,
190 applied_load: AppliedLoad,
191 solver: impl optimize::FirstOrderRootFinding<
192 FirstPiolaKirchhoffStress,
193 FirstPiolaKirchhoffTangentStiffness,
194 DeformationGradient,
195 >,
196 ) -> Result<DeformationGradient, OptimizeError>;
197}
198
199impl<T> ZerothOrderRoot for T
200where
201 T: Elastic,
202{
203 fn root(
204 &self,
205 applied_load: AppliedLoad,
206 solver: impl optimize::ZerothOrderRootFinding<DeformationGradient>,
207 ) -> Result<DeformationGradient, OptimizeError> {
208 match applied_load {
209 AppliedLoad::UniaxialStress(deformation_gradient_11) => {
210 let mut matrix = Matrix::zero(4, 9);
211 let mut vector = Vector::zero(4);
212 matrix[0][0] = 1.0;
213 matrix[1][1] = 1.0;
214 matrix[2][2] = 1.0;
215 matrix[3][5] = 1.0;
216 vector[0] = deformation_gradient_11;
217 solver.root(
218 |deformation_gradient: &DeformationGradient| {
219 Ok(self.first_piola_kirchhoff_stress(deformation_gradient)?)
220 },
221 DeformationGradient::identity(),
222 EqualityConstraint::Linear(matrix, vector),
223 )
224 }
225 AppliedLoad::BiaxialStress(deformation_gradient_11, deformation_gradient_22) => {
226 let mut matrix = Matrix::zero(5, 9);
227 let mut vector = Vector::zero(5);
228 matrix[0][0] = 1.0;
229 matrix[1][1] = 1.0;
230 matrix[2][2] = 1.0;
231 matrix[3][5] = 1.0;
232 matrix[4][4] = 1.0;
233 vector[0] = deformation_gradient_11;
234 vector[4] = deformation_gradient_22;
235 solver.root(
236 |deformation_gradient: &DeformationGradient| {
237 Ok(self.first_piola_kirchhoff_stress(deformation_gradient)?)
238 },
239 DeformationGradient::identity(),
240 EqualityConstraint::Linear(matrix, vector),
241 )
242 }
243 }
244 }
245}
246
247impl<T> FirstOrderRoot for T
248where
249 T: Elastic,
250{
251 fn root(
252 &self,
253 applied_load: AppliedLoad,
254 solver: impl optimize::FirstOrderRootFinding<
255 FirstPiolaKirchhoffStress,
256 FirstPiolaKirchhoffTangentStiffness,
257 DeformationGradient,
258 >,
259 ) -> Result<DeformationGradient, OptimizeError> {
260 match applied_load {
261 AppliedLoad::UniaxialStress(deformation_gradient_11) => {
262 let mut matrix = Matrix::zero(4, 9);
263 let mut vector = Vector::zero(4);
264 matrix[0][0] = 1.0;
265 matrix[1][1] = 1.0;
266 matrix[2][2] = 1.0;
267 matrix[3][5] = 1.0;
268 vector[0] = deformation_gradient_11;
269 solver.root(
270 |deformation_gradient: &DeformationGradient| {
271 Ok(self.first_piola_kirchhoff_stress(deformation_gradient)?)
272 },
273 |deformation_gradient: &DeformationGradient| {
274 Ok(self.first_piola_kirchhoff_tangent_stiffness(deformation_gradient)?)
275 },
276 DeformationGradient::identity(),
277 EqualityConstraint::Linear(matrix, vector),
278 )
279 }
280 AppliedLoad::BiaxialStress(deformation_gradient_11, deformation_gradient_22) => {
281 let mut matrix = Matrix::zero(5, 9);
282 let mut vector = Vector::zero(5);
283 matrix[0][0] = 1.0;
284 matrix[1][1] = 1.0;
285 matrix[2][2] = 1.0;
286 matrix[3][5] = 1.0;
287 matrix[4][4] = 1.0;
288 vector[0] = deformation_gradient_11;
289 vector[4] = deformation_gradient_22;
290 solver.root(
291 |deformation_gradient: &DeformationGradient| {
292 Ok(self.first_piola_kirchhoff_stress(deformation_gradient)?)
293 },
294 |deformation_gradient: &DeformationGradient| {
295 Ok(self.first_piola_kirchhoff_tangent_stiffness(deformation_gradient)?)
296 },
297 DeformationGradient::identity(),
298 EqualityConstraint::Linear(matrix, vector),
299 )
300 }
301 }
302 }
303}