1#[cfg(test)]
14pub mod test;
15
16use super::{super::fluid::viscous::Viscous, *};
17use crate::math::{
18 Matrix, Vector,
19 integrate::{ImplicitDaeFirstOrderRoot, ImplicitDaeZerothOrderRoot},
20 optimize::{EqualityConstraint, FirstOrderRootFinding, ZerothOrderRootFinding},
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}
139
140pub trait ZerothOrderRoot {
142 fn root(
148 &self,
149 applied_load: AppliedLoad,
150 integrator: impl ImplicitDaeZerothOrderRoot<DeformationGradient, DeformationGradients>,
151 solver: impl ZerothOrderRootFinding<DeformationGradient>,
152 ) -> Result<(Times, DeformationGradients, DeformationGradientRates), ConstitutiveError>;
153}
154
155pub trait FirstOrderRoot {
157 fn root(
163 &self,
164 applied_load: AppliedLoad,
165 integrator: impl ImplicitDaeFirstOrderRoot<
166 FirstPiolaKirchhoffStress,
167 FirstPiolaKirchhoffRateTangentStiffness,
168 DeformationGradientRate,
169 DeformationGradientRates,
170 >,
171 solver: impl FirstOrderRootFinding<
172 FirstPiolaKirchhoffStress,
173 FirstPiolaKirchhoffRateTangentStiffness,
174 DeformationGradientRate,
175 >,
176 ) -> Result<(Times, DeformationGradients, DeformationGradientRates), ConstitutiveError>;
177}
178
179impl<T> ZerothOrderRoot for T
180where
181 T: Viscoelastic,
182{
183 fn root(
184 &self,
185 applied_load: AppliedLoad,
186 integrator: impl ImplicitDaeZerothOrderRoot<DeformationGradient, DeformationGradients>,
187 solver: impl ZerothOrderRootFinding<DeformationGradientRate>,
188 ) -> Result<(Times, DeformationGradients, DeformationGradientRates), ConstitutiveError> {
189 match match applied_load {
190 AppliedLoad::UniaxialStress(deformation_gradient_rate_11, time) => {
191 let mut matrix = Matrix::zero(4, 9);
192 let mut vector = Vector::zero(4);
193 matrix[0][0] = 1.0;
194 matrix[1][1] = 1.0;
195 matrix[2][2] = 1.0;
196 matrix[3][5] = 1.0;
197 integrator.integrate(
198 |_: Scalar,
199 deformation_gradient: &DeformationGradient,
200 deformation_gradient_rate: &DeformationGradientRate| {
201 Ok(self.first_piola_kirchhoff_stress(
202 deformation_gradient,
203 deformation_gradient_rate,
204 )?)
205 },
206 solver,
207 time,
208 DeformationGradient::identity(),
209 |t: Scalar| {
210 vector[0] = deformation_gradient_rate_11(t);
211 EqualityConstraint::Linear(matrix.clone(), vector.clone())
212 },
213 )
214 }
215 AppliedLoad::BiaxialStress(
216 deformation_gradient_rate_11,
217 deformation_gradient_rate_22,
218 time,
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 integrator.integrate(
228 |_: Scalar,
229 deformation_gradient: &DeformationGradient,
230 deformation_gradient_rate: &DeformationGradientRate| {
231 Ok(self.first_piola_kirchhoff_stress(
232 deformation_gradient,
233 deformation_gradient_rate,
234 )?)
235 },
236 solver,
237 time,
238 DeformationGradient::identity(),
239 |t: Scalar| {
240 vector[0] = deformation_gradient_rate_11(t);
241 vector[4] = deformation_gradient_rate_22(t);
242 EqualityConstraint::Linear(matrix.clone(), vector.clone())
243 },
244 )
245 }
246 } {
247 Ok(results) => Ok(results),
248 Err(error) => Err(ConstitutiveError::Upstream(
249 format!("{error}"),
250 format!("{self:?}"),
251 )),
252 }
253 }
254}
255
256impl<T> FirstOrderRoot for T
257where
258 T: Viscoelastic,
259{
260 fn root(
261 &self,
262 applied_load: AppliedLoad,
263 integrator: impl ImplicitDaeFirstOrderRoot<
264 FirstPiolaKirchhoffStress,
265 FirstPiolaKirchhoffRateTangentStiffness,
266 DeformationGradientRate,
267 DeformationGradientRates,
268 >,
269 solver: impl FirstOrderRootFinding<
270 FirstPiolaKirchhoffStress,
271 FirstPiolaKirchhoffRateTangentStiffness,
272 DeformationGradientRate,
273 >,
274 ) -> Result<(Times, DeformationGradients, DeformationGradientRates), ConstitutiveError> {
275 match match applied_load {
276 AppliedLoad::UniaxialStress(deformation_gradient_rate_11, time) => {
277 let mut matrix = Matrix::zero(4, 9);
278 let mut vector = Vector::zero(4);
279 matrix[0][0] = 1.0;
280 matrix[1][1] = 1.0;
281 matrix[2][2] = 1.0;
282 matrix[3][5] = 1.0;
283 integrator.integrate(
284 |_: Scalar,
285 deformation_gradient: &DeformationGradient,
286 deformation_gradient_rate: &DeformationGradientRate| {
287 Ok(self.first_piola_kirchhoff_stress(
288 deformation_gradient,
289 deformation_gradient_rate,
290 )?)
291 },
292 |_: Scalar,
293 deformation_gradient: &DeformationGradient,
294 deformation_gradient_rate: &DeformationGradientRate| {
295 Ok(self.first_piola_kirchhoff_rate_tangent_stiffness(
296 deformation_gradient,
297 deformation_gradient_rate,
298 )?)
299 },
300 solver,
301 time,
302 DeformationGradient::identity(),
303 |t: Scalar| {
304 vector[0] = deformation_gradient_rate_11(t);
305 EqualityConstraint::Linear(matrix.clone(), vector.clone())
306 },
307 )
308 }
309 AppliedLoad::BiaxialStress(
310 deformation_gradient_rate_11,
311 deformation_gradient_rate_22,
312 time,
313 ) => {
314 let mut matrix = Matrix::zero(5, 9);
315 let mut vector = Vector::zero(5);
316 matrix[0][0] = 1.0;
317 matrix[1][1] = 1.0;
318 matrix[2][2] = 1.0;
319 matrix[3][5] = 1.0;
320 matrix[4][4] = 1.0;
321 integrator.integrate(
322 |_: Scalar,
323 deformation_gradient: &DeformationGradient,
324 deformation_gradient_rate: &DeformationGradientRate| {
325 Ok(self.first_piola_kirchhoff_stress(
326 deformation_gradient,
327 deformation_gradient_rate,
328 )?)
329 },
330 |_: Scalar,
331 deformation_gradient: &DeformationGradient,
332 deformation_gradient_rate: &DeformationGradientRate| {
333 Ok(self.first_piola_kirchhoff_rate_tangent_stiffness(
334 deformation_gradient,
335 deformation_gradient_rate,
336 )?)
337 },
338 solver,
339 time,
340 DeformationGradient::identity(),
341 |t: Scalar| {
342 vector[0] = deformation_gradient_rate_11(t);
343 vector[4] = deformation_gradient_rate_22(t);
344 EqualityConstraint::Linear(matrix.clone(), vector.clone())
345 },
346 )
347 }
348 } {
349 Ok(results) => Ok(results),
350 Err(error) => Err(ConstitutiveError::Upstream(
351 format!("{error}"),
352 format!("{self:?}"),
353 )),
354 }
355 }
356}