conspire/constitutive/solid/hyperelastic_viscoplastic/
mod.rs

1//! Hyperelastic-viscoplastic solid constitutive models.
2
3#[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
29/// Required methods for hyperelastic-viscoplastic solid constitutive models.
30pub trait HyperelasticViscoplastic<Y>
31where
32    Self: ElasticViscoplastic<Y>,
33    Y: Tensor,
34{
35    /// Calculates and returns the Helmholtz free energy density.
36    ///
37    /// ```math
38    /// a = a(\mathbf{F}_\mathrm{e})
39    /// ```
40    fn helmholtz_free_energy_density(
41        &self,
42        deformation_gradient: &DeformationGradient,
43        deformation_gradient_p: &DeformationGradientPlastic,
44    ) -> Result<Scalar, ConstitutiveError>;
45}
46
47/// First-order minimization methods for elastic-viscoplastic solid constitutive models.
48pub trait FirstOrderMinimize<Y>
49where
50    Y: Tensor,
51{
52    /// Solve for the unknown components of the deformation gradients under an applied load.
53    ///
54    /// ```math
55    /// \Pi(\mathbf{F},\mathbf{F}_\mathrm{p},\boldsymbol{\lambda}) = a(\mathbf{F},\mathbf{F}_\mathrm{p}) - \boldsymbol{\lambda}:(\mathbf{F} - \mathbf{F}_0) - \mathbf{P}_0:\mathbf{F}
56    /// ```
57    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
78/// Second-order minimization methods for elastic-viscoplastic solid constitutive models.
79pub trait SecondOrderMinimize<Y>
80where
81    Y: Tensor,
82{
83    /// Solve for the unknown components of the deformation gradients under an applied load.
84    ///
85    /// ```math
86    /// \Pi(\mathbf{F},\mathbf{F}_\mathrm{p},\boldsymbol{\lambda}) = a(\mathbf{F},\mathbf{F}_\mathrm{p}) - \boldsymbol{\lambda}:(\mathbf{F} - \mathbf{F}_0) - \mathbf{P}_0:\mathbf{F}
87    /// ```
88    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}