1#[cfg(test)]
4pub mod test;
5
6mod hencky;
7mod saint_venant_kirchhoff;
8
9pub use hencky::Hencky;
10pub use saint_venant_kirchhoff::SaintVenantKirchhoff;
11
12use crate::{
13 constitutive::{
14 ConstitutiveError,
15 fluid::viscoplastic::{ViscoplasticStateVariables, ViscoplasticStateVariablesHistory},
16 solid::elastic_viscoplastic::{AppliedLoad, ElasticViscoplastic},
17 },
18 math::{
19 Matrix, Tensor, TensorArray, Vector,
20 integrate::{ExplicitDaeFirstOrderMinimize, ExplicitDaeSecondOrderMinimize},
21 optimize::{EqualityConstraint, FirstOrderOptimization, SecondOrderOptimization},
22 },
23 mechanics::{
24 DeformationGradient, DeformationGradientPlastic, DeformationGradients,
25 FirstPiolaKirchhoffStress, FirstPiolaKirchhoffTangentStiffness, Scalar, Times,
26 },
27};
28
29pub trait HyperelasticViscoplastic<Y>
31where
32 Self: ElasticViscoplastic<Y>,
33 Y: Tensor,
34{
35 fn helmholtz_free_energy_density(
41 &self,
42 deformation_gradient: &DeformationGradient,
43 deformation_gradient_p: &DeformationGradientPlastic,
44 ) -> Result<Scalar, ConstitutiveError>;
45}
46
47pub trait FirstOrderMinimize<Y>
49where
50 Y: Tensor,
51{
52 fn minimize(
58 &self,
59 applied_load: AppliedLoad,
60 integrator: impl ExplicitDaeFirstOrderMinimize<
61 Scalar,
62 ViscoplasticStateVariables<Y>,
63 DeformationGradient,
64 ViscoplasticStateVariablesHistory<Y>,
65 DeformationGradients,
66 >,
67 solver: impl FirstOrderOptimization<Scalar, DeformationGradient>,
68 ) -> Result<
69 (
70 Times,
71 DeformationGradients,
72 ViscoplasticStateVariablesHistory<Y>,
73 ),
74 ConstitutiveError,
75 >;
76}
77
78pub trait SecondOrderMinimize<Y>
80where
81 Y: Tensor,
82{
83 fn minimize(
89 &self,
90 applied_load: AppliedLoad,
91 integrator: impl ExplicitDaeSecondOrderMinimize<
92 Scalar,
93 FirstPiolaKirchhoffStress,
94 FirstPiolaKirchhoffTangentStiffness,
95 ViscoplasticStateVariables<Y>,
96 DeformationGradient,
97 ViscoplasticStateVariablesHistory<Y>,
98 DeformationGradients,
99 >,
100 solver: impl SecondOrderOptimization<
101 Scalar,
102 FirstPiolaKirchhoffStress,
103 FirstPiolaKirchhoffTangentStiffness,
104 DeformationGradient,
105 >,
106 ) -> Result<
107 (
108 Times,
109 DeformationGradients,
110 ViscoplasticStateVariablesHistory<Y>,
111 ),
112 ConstitutiveError,
113 >;
114}
115
116impl<C, Y> FirstOrderMinimize<Y> for C
117where
118 C: HyperelasticViscoplastic<Y>,
119 Y: Tensor,
120{
121 fn minimize(
122 &self,
123 applied_load: AppliedLoad,
124 integrator: impl ExplicitDaeFirstOrderMinimize<
125 Scalar,
126 ViscoplasticStateVariables<Y>,
127 DeformationGradient,
128 ViscoplasticStateVariablesHistory<Y>,
129 DeformationGradients,
130 >,
131 solver: impl FirstOrderOptimization<Scalar, DeformationGradient>,
132 ) -> Result<
133 (
134 Times,
135 DeformationGradients,
136 ViscoplasticStateVariablesHistory<Y>,
137 ),
138 ConstitutiveError,
139 > {
140 match match applied_load {
141 AppliedLoad::UniaxialStress(deformation_gradient_11, time) => {
142 let mut matrix = Matrix::zero(4, 9);
143 let mut vector = Vector::zero(4);
144 matrix[0][0] = 1.0;
145 matrix[1][1] = 1.0;
146 matrix[2][2] = 1.0;
147 matrix[3][5] = 1.0;
148 integrator.integrate(
149 |_: Scalar,
150 state_variables: &ViscoplasticStateVariables<Y>,
151 deformation_gradient: &DeformationGradient| {
152 Ok(self.state_variables_evolution(deformation_gradient, state_variables)?)
153 },
154 |_: Scalar,
155 state_variables: &ViscoplasticStateVariables<Y>,
156 deformation_gradient: &DeformationGradient| {
157 let deformation_gradient_p = &state_variables.0;
158 Ok(self.helmholtz_free_energy_density(
159 deformation_gradient,
160 deformation_gradient_p,
161 )?)
162 },
163 |_: Scalar,
164 state_variables: &ViscoplasticStateVariables<Y>,
165 deformation_gradient: &DeformationGradient| {
166 let deformation_gradient_p = &state_variables.0;
167 Ok(self.first_piola_kirchhoff_stress(
168 deformation_gradient,
169 deformation_gradient_p,
170 )?)
171 },
172 solver,
173 time,
174 (self.initial_state(), DeformationGradient::identity()),
175 |t: Scalar| {
176 vector[0] = deformation_gradient_11(t);
177 EqualityConstraint::Linear(matrix.clone(), vector.clone())
178 },
179 )
180 }
181 } {
182 Ok((times, state_variables, _, deformation_gradients)) => {
183 Ok((times, deformation_gradients, state_variables))
184 }
185 Err(error) => Err(ConstitutiveError::Upstream(
186 format!("{error}"),
187 format!("{self:?}"),
188 )),
189 }
190 }
191}
192
193impl<C, Y> SecondOrderMinimize<Y> for C
194where
195 C: HyperelasticViscoplastic<Y>,
196 Y: Tensor,
197{
198 fn minimize(
199 &self,
200 applied_load: AppliedLoad,
201 integrator: impl ExplicitDaeSecondOrderMinimize<
202 Scalar,
203 FirstPiolaKirchhoffStress,
204 FirstPiolaKirchhoffTangentStiffness,
205 ViscoplasticStateVariables<Y>,
206 DeformationGradient,
207 ViscoplasticStateVariablesHistory<Y>,
208 DeformationGradients,
209 >,
210 solver: impl SecondOrderOptimization<
211 Scalar,
212 FirstPiolaKirchhoffStress,
213 FirstPiolaKirchhoffTangentStiffness,
214 DeformationGradient,
215 >,
216 ) -> Result<
217 (
218 Times,
219 DeformationGradients,
220 ViscoplasticStateVariablesHistory<Y>,
221 ),
222 ConstitutiveError,
223 > {
224 match match applied_load {
225 AppliedLoad::UniaxialStress(deformation_gradient_11, time) => {
226 let mut matrix = Matrix::zero(4, 9);
227 let mut vector = Vector::zero(4);
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 integrator.integrate(
233 |_: Scalar,
234 state_variables: &ViscoplasticStateVariables<Y>,
235 deformation_gradient: &DeformationGradient| {
236 Ok(self.state_variables_evolution(deformation_gradient, state_variables)?)
237 },
238 |_: Scalar,
239 state_variables: &ViscoplasticStateVariables<Y>,
240 deformation_gradient: &DeformationGradient| {
241 let deformation_gradient_p = &state_variables.0;
242 Ok(self.helmholtz_free_energy_density(
243 deformation_gradient,
244 deformation_gradient_p,
245 )?)
246 },
247 |_: Scalar,
248 state_variables: &ViscoplasticStateVariables<Y>,
249 deformation_gradient: &DeformationGradient| {
250 let deformation_gradient_p = &state_variables.0;
251 Ok(self.first_piola_kirchhoff_stress(
252 deformation_gradient,
253 deformation_gradient_p,
254 )?)
255 },
256 |_: Scalar,
257 state_variables: &ViscoplasticStateVariables<Y>,
258 deformation_gradient: &DeformationGradient| {
259 let deformation_gradient_p = &state_variables.0;
260 Ok(self.first_piola_kirchhoff_tangent_stiffness(
261 deformation_gradient,
262 deformation_gradient_p,
263 )?)
264 },
265 solver,
266 time,
267 (self.initial_state(), DeformationGradient::identity()),
268 |t: Scalar| {
269 vector[0] = deformation_gradient_11(t);
270 EqualityConstraint::Linear(matrix.clone(), vector.clone())
271 },
272 None,
273 )
274 }
275 } {
276 Ok((times, state_variables, _, deformation_gradients)) => {
277 Ok((times, deformation_gradients, state_variables))
278 }
279 Err(error) => Err(ConstitutiveError::Upstream(
280 format!("{error}"),
281 format!("{self:?}"),
282 )),
283 }
284 }
285}