conspire/constitutive/solid/viscoelastic/
mod.rs1#[cfg(test)]
14pub mod test;
15
16use super::{super::fluid::viscous::Viscous, *};
17use crate::math::{
18 Matrix, TensorVec, Vector,
19 integrate::{Explicit, IntegrationError},
20 optimize::{EqualityConstraint, FirstOrderRootFinding, NewtonRaphson, OptimizeError},
21};
22
23pub enum AppliedLoad<'a> {
25 UniaxialStress(fn(Scalar) -> Scalar, &'a [Scalar]),
27 BiaxialStress(fn(Scalar) -> Scalar, fn(Scalar) -> Scalar, &'a [Scalar]),
29}
30
31pub trait Viscoelastic
33where
34 Self: Solid + Viscous,
35{
36 fn cauchy_stress(
42 &self,
43 deformation_gradient: &DeformationGradient,
44 deformation_gradient_rate: &DeformationGradientRate,
45 ) -> Result<CauchyStress, ConstitutiveError> {
46 Ok(deformation_gradient
47 * self
48 .second_piola_kirchhoff_stress(deformation_gradient, deformation_gradient_rate)?
49 * deformation_gradient.transpose()
50 / deformation_gradient.determinant())
51 }
52 fn cauchy_rate_tangent_stiffness(
58 &self,
59 deformation_gradient: &DeformationGradient,
60 deformation_gradient_rate: &DeformationGradientRate,
61 ) -> Result<CauchyRateTangentStiffness, ConstitutiveError> {
62 Ok(self
63 .second_piola_kirchhoff_rate_tangent_stiffness(
64 deformation_gradient,
65 deformation_gradient_rate,
66 )?
67 .contract_first_second_indices_with_second_indices_of(
68 deformation_gradient,
69 deformation_gradient,
70 )
71 / deformation_gradient.determinant())
72 }
73 fn first_piola_kirchhoff_stress(
79 &self,
80 deformation_gradient: &DeformationGradient,
81 deformation_gradient_rate: &DeformationGradientRate,
82 ) -> Result<FirstPiolaKirchhoffStress, ConstitutiveError> {
83 Ok(
84 self.cauchy_stress(deformation_gradient, deformation_gradient_rate)?
85 * deformation_gradient.inverse_transpose()
86 * deformation_gradient.determinant(),
87 )
88 }
89 fn first_piola_kirchhoff_rate_tangent_stiffness(
95 &self,
96 deformation_gradient: &DeformationGradient,
97 deformation_gradient_rate: &DeformationGradientRate,
98 ) -> Result<FirstPiolaKirchhoffRateTangentStiffness, ConstitutiveError> {
99 Ok(self
100 .cauchy_rate_tangent_stiffness(deformation_gradient, deformation_gradient_rate)?
101 .contract_second_index_with_first_index_of(&deformation_gradient.inverse_transpose())
102 * deformation_gradient.determinant())
103 }
104 fn second_piola_kirchhoff_stress(
110 &self,
111 deformation_gradient: &DeformationGradient,
112 deformation_gradient_rate: &DeformationGradientRate,
113 ) -> Result<SecondPiolaKirchhoffStress, ConstitutiveError> {
114 Ok(deformation_gradient.inverse()
115 * self.cauchy_stress(deformation_gradient, deformation_gradient_rate)?
116 * deformation_gradient.inverse_transpose()
117 * deformation_gradient.determinant())
118 }
119 fn second_piola_kirchhoff_rate_tangent_stiffness(
125 &self,
126 deformation_gradient: &DeformationGradient,
127 deformation_gradient_rate: &DeformationGradientRate,
128 ) -> Result<SecondPiolaKirchhoffRateTangentStiffness, ConstitutiveError> {
129 let deformation_gradient_inverse = deformation_gradient.inverse();
130 Ok(self
131 .cauchy_rate_tangent_stiffness(deformation_gradient, deformation_gradient_rate)?
132 .contract_first_second_indices_with_second_indices_of(
133 &deformation_gradient_inverse,
134 &deformation_gradient_inverse,
135 )
136 * deformation_gradient.determinant())
137 }
138 fn root(
144 &self,
145 applied_load: AppliedLoad,
146 integrator: impl Explicit<DeformationGradientRate, DeformationGradientRates>,
147 ) -> Result<(Times, DeformationGradients, DeformationGradientRates), IntegrationError> {
148 match applied_load {
149 AppliedLoad::UniaxialStress(deformation_gradient_rate_11, time) => integrator
150 .integrate(
151 |t: Scalar, deformation_gradient: &DeformationGradient| {
152 Ok(self.root_uniaxial_inner(
153 deformation_gradient,
154 deformation_gradient_rate_11(t),
155 )?)
156 },
157 time,
158 DeformationGradient::identity(),
159 ),
160 AppliedLoad::BiaxialStress(
161 deformation_gradient_rate_11,
162 deformation_gradient_rate_22,
163 time,
164 ) => integrator.integrate(
165 |t: Scalar, deformation_gradient: &DeformationGradient| {
166 Ok(self.root_biaxial_inner(
167 deformation_gradient,
168 deformation_gradient_rate_11(t),
169 deformation_gradient_rate_22(t),
170 )?)
171 },
172 time,
173 DeformationGradient::identity(),
174 ),
175 }
176 }
177 #[doc(hidden)]
178 fn root_uniaxial_inner(
179 &self,
180 deformation_gradient: &DeformationGradient,
181 deformation_gradient_rate_11: Scalar,
182 ) -> Result<DeformationGradientRate, OptimizeError> {
183 let solver = NewtonRaphson {
184 ..Default::default()
185 };
186 let mut matrix = Matrix::zero(4, 9);
187 let mut vector = Vector::zero(4);
188 matrix[0][0] = 1.0;
189 matrix[1][1] = 1.0;
190 matrix[2][2] = 1.0;
191 matrix[3][5] = 1.0;
192 vector[0] = deformation_gradient_rate_11;
193 solver.root(
194 |deformation_gradient_rate: &DeformationGradientRate| {
195 Ok(self.first_piola_kirchhoff_stress(
196 deformation_gradient,
197 deformation_gradient_rate,
198 )?)
199 },
200 |deformation_gradient_rate: &DeformationGradientRate| {
201 Ok(self.first_piola_kirchhoff_rate_tangent_stiffness(
202 deformation_gradient,
203 deformation_gradient_rate,
204 )?)
205 },
206 DeformationGradientRate::zero(),
207 EqualityConstraint::Linear(matrix, vector),
208 )
209 }
210 #[doc(hidden)]
211 fn root_biaxial_inner(
212 &self,
213 deformation_gradient: &DeformationGradient,
214 deformation_gradient_rate_11: Scalar,
215 deformation_gradient_rate_22: Scalar,
216 ) -> Result<DeformationGradientRate, OptimizeError> {
217 let solver = NewtonRaphson {
218 ..Default::default()
219 };
220 let mut matrix = Matrix::zero(5, 9);
221 let mut vector = Vector::zero(5);
222 matrix[0][0] = 1.0;
223 matrix[1][1] = 1.0;
224 matrix[2][2] = 1.0;
225 matrix[3][5] = 1.0;
226 matrix[4][4] = 1.0;
227 vector[0] = deformation_gradient_rate_11;
228 vector[4] = deformation_gradient_rate_22;
229 solver.root(
230 |deformation_gradient_rate: &DeformationGradientRate| {
231 Ok(self.first_piola_kirchhoff_stress(
232 deformation_gradient,
233 deformation_gradient_rate,
234 )?)
235 },
236 |deformation_gradient_rate: &DeformationGradientRate| {
237 Ok(self.first_piola_kirchhoff_rate_tangent_stiffness(
238 deformation_gradient,
239 deformation_gradient_rate,
240 )?)
241 },
242 DeformationGradientRate::zero(),
243 EqualityConstraint::Linear(matrix, vector),
244 )
245 }
246}