conspire/constitutive/solid/elastic/
mod.rs1#![doc = include_str!("doc.md")]
6
7#[cfg(test)]
8pub mod test;
9
10mod almansi_hamel;
11
12pub use almansi_hamel::AlmansiHamel;
13
14use super::*;
15use crate::math::{
16 Matrix, TensorVec, Vector,
17 optimize::{EqualityConstraint, FirstOrderRootFinding, NewtonRaphson, OptimizeError},
18};
19
20pub enum AppliedLoad {
22 UniaxialStress(Scalar),
24 BiaxialStress(Scalar, Scalar),
26}
27
28pub trait Elastic
30where
31 Self: Solid,
32{
33 fn cauchy_stress(
39 &self,
40 deformation_gradient: &DeformationGradient,
41 ) -> Result<CauchyStress, ConstitutiveError> {
42 Ok(deformation_gradient
43 * self.second_piola_kirchhoff_stress(deformation_gradient)?
44 * deformation_gradient.transpose()
45 / deformation_gradient.determinant())
46 }
47 fn cauchy_tangent_stiffness(
53 &self,
54 deformation_gradient: &DeformationGradient,
55 ) -> Result<CauchyTangentStiffness, ConstitutiveError> {
56 let deformation_gradient_inverse_transpose = deformation_gradient.inverse_transpose();
57 let cauchy_stress = self.cauchy_stress(deformation_gradient)?;
58 let some_stress = &cauchy_stress * &deformation_gradient_inverse_transpose;
59 Ok(self
60 .second_piola_kirchhoff_tangent_stiffness(deformation_gradient)?
61 .contract_first_second_indices_with_second_indices_of(
62 deformation_gradient,
63 deformation_gradient,
64 )
65 / deformation_gradient.determinant()
66 - CauchyTangentStiffness::dyad_ij_kl(
67 &cauchy_stress,
68 &deformation_gradient_inverse_transpose,
69 )
70 + CauchyTangentStiffness::dyad_il_kj(&some_stress, &IDENTITY)
71 + CauchyTangentStiffness::dyad_ik_jl(&IDENTITY, &some_stress))
72 }
73 fn first_piola_kirchhoff_stress(
79 &self,
80 deformation_gradient: &DeformationGradient,
81 ) -> Result<FirstPiolaKirchhoffStress, ConstitutiveError> {
82 Ok(self.cauchy_stress(deformation_gradient)?
83 * deformation_gradient.inverse_transpose()
84 * deformation_gradient.determinant())
85 }
86 fn first_piola_kirchhoff_tangent_stiffness(
92 &self,
93 deformation_gradient: &DeformationGradient,
94 ) -> Result<FirstPiolaKirchhoffTangentStiffness, ConstitutiveError> {
95 let deformation_gradient_inverse_transpose = deformation_gradient.inverse_transpose();
96 let first_piola_kirchhoff_stress =
97 self.first_piola_kirchhoff_stress(deformation_gradient)?;
98 Ok(self
99 .cauchy_tangent_stiffness(deformation_gradient)?
100 .contract_second_index_with_first_index_of(&deformation_gradient_inverse_transpose)
101 * deformation_gradient.determinant()
102 + FirstPiolaKirchhoffTangentStiffness::dyad_ij_kl(
103 &first_piola_kirchhoff_stress,
104 &deformation_gradient_inverse_transpose,
105 )
106 - FirstPiolaKirchhoffTangentStiffness::dyad_il_kj(
107 &first_piola_kirchhoff_stress,
108 &deformation_gradient_inverse_transpose,
109 ))
110 }
111 fn second_piola_kirchhoff_stress(
117 &self,
118 deformation_gradient: &DeformationGradient,
119 ) -> Result<SecondPiolaKirchhoffStress, ConstitutiveError> {
120 Ok(deformation_gradient.inverse()
121 * self.cauchy_stress(deformation_gradient)?
122 * deformation_gradient.inverse_transpose()
123 * deformation_gradient.determinant())
124 }
125 fn second_piola_kirchhoff_tangent_stiffness(
131 &self,
132 deformation_gradient: &DeformationGradient,
133 ) -> Result<SecondPiolaKirchhoffTangentStiffness, ConstitutiveError> {
134 let deformation_gradient_inverse_transpose = deformation_gradient.inverse_transpose();
135 let deformation_gradient_inverse = deformation_gradient_inverse_transpose.transpose();
136 let second_piola_kirchhoff_stress =
137 self.second_piola_kirchhoff_stress(deformation_gradient)?;
138 Ok(self
139 .cauchy_tangent_stiffness(deformation_gradient)?
140 .contract_first_second_indices_with_second_indices_of(
141 &deformation_gradient_inverse,
142 &deformation_gradient_inverse,
143 )
144 * deformation_gradient.determinant()
145 + SecondPiolaKirchhoffTangentStiffness::dyad_ij_kl(
146 &second_piola_kirchhoff_stress,
147 &deformation_gradient_inverse_transpose,
148 )
149 - SecondPiolaKirchhoffTangentStiffness::dyad_il_kj(
150 &second_piola_kirchhoff_stress,
151 &deformation_gradient_inverse_transpose,
152 )
153 - SecondPiolaKirchhoffTangentStiffness::dyad_ik_jl(
154 &deformation_gradient_inverse,
155 &second_piola_kirchhoff_stress,
156 ))
157 }
158 fn root(&self, applied_load: AppliedLoad) -> Result<DeformationGradient, OptimizeError> {
164 let solver = NewtonRaphson {
165 ..Default::default()
166 };
167 match applied_load {
168 AppliedLoad::UniaxialStress(deformation_gradient_11) => {
169 let mut matrix = Matrix::zero(4, 9);
170 let mut vector = Vector::zero(4);
171 matrix[0][0] = 1.0;
172 matrix[1][1] = 1.0;
173 matrix[2][2] = 1.0;
174 matrix[3][5] = 1.0;
175 vector[0] = deformation_gradient_11;
176 solver.root(
177 |deformation_gradient: &DeformationGradient| {
178 Ok(self.first_piola_kirchhoff_stress(deformation_gradient)?)
179 },
180 |deformation_gradient: &DeformationGradient| {
181 Ok(self.first_piola_kirchhoff_tangent_stiffness(deformation_gradient)?)
182 },
183 DeformationGradient::identity(),
184 EqualityConstraint::Linear(matrix, vector),
185 )
186 }
187 AppliedLoad::BiaxialStress(deformation_gradient_11, deformation_gradient_22) => {
188 let mut matrix = Matrix::zero(5, 9);
189 let mut vector = Vector::zero(5);
190 matrix[0][0] = 1.0;
191 matrix[1][1] = 1.0;
192 matrix[2][2] = 1.0;
193 matrix[3][5] = 1.0;
194 matrix[4][4] = 1.0;
195 vector[0] = deformation_gradient_11;
196 vector[4] = deformation_gradient_22;
197 solver.root(
198 |deformation_gradient: &DeformationGradient| {
199 Ok(self.first_piola_kirchhoff_stress(deformation_gradient)?)
200 },
201 |deformation_gradient: &DeformationGradient| {
202 Ok(self.first_piola_kirchhoff_tangent_stiffness(deformation_gradient)?)
203 },
204 DeformationGradient::identity(),
205 EqualityConstraint::Linear(matrix, vector),
206 )
207 }
208 }
209 }
210}