1#[cfg(test)]
22pub mod test;
23
24mod almansi_hamel;
25
26pub use almansi_hamel::AlmansiHamel;
27
28use super::{
29 viscoelastic::{AppliedLoad, Viscoelastic},
30 *,
31};
32use crate::math::{
33 Matrix, Vector,
34 integrate::{ImplicitDaeFirstOrderMinimize, ImplicitDaeSecondOrderMinimize},
35 optimize::{EqualityConstraint, FirstOrderOptimization, SecondOrderOptimization},
36};
37
38pub trait ElasticHyperviscous
40where
41 Self: Viscoelastic,
42{
43 fn dissipation_potential(
49 &self,
50 deformation_gradient: &DeformationGradient,
51 deformation_gradient_rate: &DeformationGradientRate,
52 ) -> Result<Scalar, ConstitutiveError> {
53 Ok(self
54 .first_piola_kirchhoff_stress(deformation_gradient, &ZERO_10)?
55 .full_contraction(deformation_gradient_rate)
56 + self.viscous_dissipation(deformation_gradient, deformation_gradient_rate)?)
57 }
58 fn viscous_dissipation(
64 &self,
65 deformation_gradient: &DeformationGradient,
66 deformation_gradient_rate: &DeformationGradientRate,
67 ) -> Result<Scalar, ConstitutiveError>;
68}
69
70pub trait FirstOrderMinimize {
72 fn minimize(
78 &self,
79 applied_load: AppliedLoad,
80 integrator: impl ImplicitDaeFirstOrderMinimize<
81 Scalar,
82 DeformationGradientRate,
83 DeformationGradientRates,
84 >,
85 solver: impl FirstOrderOptimization<Scalar, DeformationGradient>,
86 ) -> Result<(Times, DeformationGradients, DeformationGradientRates), ConstitutiveError>;
87}
88
89pub trait SecondOrderMinimize {
91 fn minimize(
97 &self,
98 applied_load: AppliedLoad,
99 integrator: impl ImplicitDaeSecondOrderMinimize<
100 Scalar,
101 FirstPiolaKirchhoffStress,
102 FirstPiolaKirchhoffRateTangentStiffness,
103 DeformationGradientRate,
104 DeformationGradientRates,
105 >,
106 solver: impl SecondOrderOptimization<
107 Scalar,
108 FirstPiolaKirchhoffStress,
109 FirstPiolaKirchhoffRateTangentStiffness,
110 DeformationGradient,
111 >,
112 ) -> Result<(Times, DeformationGradients, DeformationGradientRates), ConstitutiveError>;
113}
114
115impl<T> FirstOrderMinimize for T
116where
117 T: ElasticHyperviscous,
118{
119 fn minimize(
120 &self,
121 applied_load: AppliedLoad,
122 integrator: impl ImplicitDaeFirstOrderMinimize<
123 Scalar,
124 DeformationGradientRate,
125 DeformationGradientRates,
126 >,
127 solver: impl FirstOrderOptimization<Scalar, DeformationGradientRate>,
128 ) -> Result<(Times, DeformationGradients, DeformationGradientRates), ConstitutiveError> {
129 match match applied_load {
130 AppliedLoad::UniaxialStress(deformation_gradient_rate_11, time) => {
131 let mut matrix = Matrix::zero(4, 9);
132 let mut vector = Vector::zero(4);
133 matrix[0][0] = 1.0;
134 matrix[1][1] = 1.0;
135 matrix[2][2] = 1.0;
136 matrix[3][5] = 1.0;
137 integrator.integrate(
138 |_: Scalar,
139 deformation_gradient: &DeformationGradient,
140 deformation_gradient_rate: &DeformationGradientRate| {
141 Ok(self.dissipation_potential(
142 deformation_gradient,
143 deformation_gradient_rate,
144 )?)
145 },
146 |_: Scalar,
147 deformation_gradient: &DeformationGradient,
148 deformation_gradient_rate: &DeformationGradientRate| {
149 Ok(self.first_piola_kirchhoff_stress(
150 deformation_gradient,
151 deformation_gradient_rate,
152 )?)
153 },
154 solver,
155 time,
156 DeformationGradient::identity(),
157 |t: Scalar| {
158 vector[0] = deformation_gradient_rate_11(t);
159 EqualityConstraint::Linear(matrix.clone(), vector.clone())
160 },
161 )
162 }
163 AppliedLoad::BiaxialStress(
164 deformation_gradient_rate_11,
165 deformation_gradient_rate_22,
166 time,
167 ) => {
168 let mut matrix = Matrix::zero(5, 9);
169 let mut vector = Vector::zero(5);
170 matrix[0][0] = 1.0;
171 matrix[1][1] = 1.0;
172 matrix[2][2] = 1.0;
173 matrix[3][5] = 1.0;
174 matrix[4][4] = 1.0;
175 integrator.integrate(
176 |_: Scalar,
177 deformation_gradient: &DeformationGradient,
178 deformation_gradient_rate: &DeformationGradientRate| {
179 Ok(self.dissipation_potential(
180 deformation_gradient,
181 deformation_gradient_rate,
182 )?)
183 },
184 |_: Scalar,
185 deformation_gradient: &DeformationGradient,
186 deformation_gradient_rate: &DeformationGradientRate| {
187 Ok(self.first_piola_kirchhoff_stress(
188 deformation_gradient,
189 deformation_gradient_rate,
190 )?)
191 },
192 solver,
193 time,
194 DeformationGradient::identity(),
195 |t: Scalar| {
196 vector[0] = deformation_gradient_rate_11(t);
197 vector[4] = deformation_gradient_rate_22(t);
198 EqualityConstraint::Linear(matrix.clone(), vector.clone())
199 },
200 )
201 }
202 } {
203 Ok(results) => Ok(results),
204 Err(error) => Err(ConstitutiveError::Upstream(
205 format!("{error}"),
206 format!("{self:?}"),
207 )),
208 }
209 }
210}
211
212impl<T> SecondOrderMinimize for T
213where
214 T: ElasticHyperviscous,
215{
216 fn minimize(
217 &self,
218 applied_load: AppliedLoad,
219 integrator: impl ImplicitDaeSecondOrderMinimize<
220 Scalar,
221 FirstPiolaKirchhoffStress,
222 FirstPiolaKirchhoffRateTangentStiffness,
223 DeformationGradientRate,
224 DeformationGradientRates,
225 >,
226 solver: impl SecondOrderOptimization<
227 Scalar,
228 FirstPiolaKirchhoffStress,
229 FirstPiolaKirchhoffRateTangentStiffness,
230 DeformationGradientRate,
231 >,
232 ) -> Result<(Times, DeformationGradients, DeformationGradientRates), ConstitutiveError> {
233 match match applied_load {
234 AppliedLoad::UniaxialStress(deformation_gradient_rate_11, time) => {
235 let mut matrix = Matrix::zero(4, 9);
236 let mut vector = Vector::zero(4);
237 matrix[0][0] = 1.0;
238 matrix[1][1] = 1.0;
239 matrix[2][2] = 1.0;
240 matrix[3][5] = 1.0;
241 integrator.integrate(
242 |_: Scalar,
243 deformation_gradient: &DeformationGradient,
244 deformation_gradient_rate: &DeformationGradientRate| {
245 Ok(self.dissipation_potential(
246 deformation_gradient,
247 deformation_gradient_rate,
248 )?)
249 },
250 |_: Scalar,
251 deformation_gradient: &DeformationGradient,
252 deformation_gradient_rate: &DeformationGradientRate| {
253 Ok(self.first_piola_kirchhoff_stress(
254 deformation_gradient,
255 deformation_gradient_rate,
256 )?)
257 },
258 |_: Scalar,
259 deformation_gradient: &DeformationGradient,
260 deformation_gradient_rate: &DeformationGradientRate| {
261 Ok(self.first_piola_kirchhoff_rate_tangent_stiffness(
262 deformation_gradient,
263 deformation_gradient_rate,
264 )?)
265 },
266 solver,
267 time,
268 DeformationGradient::identity(),
269 |t: Scalar| {
270 vector[0] = deformation_gradient_rate_11(t);
271 EqualityConstraint::Linear(matrix.clone(), vector.clone())
272 },
273 None,
274 )
275 }
276 AppliedLoad::BiaxialStress(
277 deformation_gradient_rate_11,
278 deformation_gradient_rate_22,
279 time,
280 ) => {
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 integrator.integrate(
289 |_: Scalar,
290 deformation_gradient: &DeformationGradient,
291 deformation_gradient_rate: &DeformationGradientRate| {
292 Ok(self.dissipation_potential(
293 deformation_gradient,
294 deformation_gradient_rate,
295 )?)
296 },
297 |_: Scalar,
298 deformation_gradient: &DeformationGradient,
299 deformation_gradient_rate: &DeformationGradientRate| {
300 Ok(self.first_piola_kirchhoff_stress(
301 deformation_gradient,
302 deformation_gradient_rate,
303 )?)
304 },
305 |_: Scalar,
306 deformation_gradient: &DeformationGradient,
307 deformation_gradient_rate: &DeformationGradientRate| {
308 Ok(self.first_piola_kirchhoff_rate_tangent_stiffness(
309 deformation_gradient,
310 deformation_gradient_rate,
311 )?)
312 },
313 solver,
314 time,
315 DeformationGradient::identity(),
316 |t: Scalar| {
317 vector[0] = deformation_gradient_rate_11(t);
318 vector[4] = deformation_gradient_rate_22(t);
319 EqualityConstraint::Linear(matrix.clone(), vector.clone())
320 },
321 None,
322 )
323 }
324 } {
325 Ok(results) => Ok(results),
326 Err(error) => Err(ConstitutiveError::Upstream(
327 format!("{error}"),
328 format!("{self:?}"),
329 )),
330 }
331 }
332}