Skip to main content

conspire/constitutive/solid/hyperelastic/
mod.rs

1//! Hyperelastic solid constitutive models.
2//!
3//! ---
4//!
5#![doc = include_str!("doc.md")]
6
7#[cfg(feature = "doc")]
8pub mod doc;
9
10#[cfg(test)]
11pub mod test;
12
13pub mod internal_variables;
14
15mod arruda_boyce;
16mod eight_chain;
17mod fung;
18mod gent;
19mod hencky;
20mod mooney_rivlin;
21mod neo_hookean;
22mod saint_venant_kirchhoff;
23mod yeoh;
24
25pub use self::{
26    arruda_boyce::ArrudaBoyce, eight_chain::EightChain, fung::Fung, gent::Gent, hencky::Hencky,
27    mooney_rivlin::MooneyRivlin, neo_hookean::NeoHookean,
28    saint_venant_kirchhoff::SaintVenantKirchhoff, yeoh::Yeoh,
29};
30use super::{
31    elastic::{AppliedLoad, Elastic, bcs},
32    *,
33};
34use crate::math::optimize::{EqualityConstraint, FirstOrderOptimization, SecondOrderOptimization};
35
36/// Required methods for hyperelastic solid constitutive models.
37pub trait Hyperelastic
38where
39    Self: Elastic,
40{
41    /// Calculates and returns the Helmholtz free energy density.
42    ///
43    /// ```math
44    /// a = a(\mathbf{F})
45    /// ```
46    fn helmholtz_free_energy_density(
47        &self,
48        deformation_gradient: &DeformationGradient,
49    ) -> Result<Scalar, ConstitutiveError>;
50}
51
52/// First-order minimization methods for elastic solid constitutive models.
53pub trait FirstOrderMinimize {
54    /// Solve for the unknown components of the deformation gradient under an applied load.
55    ///
56    /// ```math
57    /// \Pi(\mathbf{F},\boldsymbol{\lambda}) = a(\mathbf{F}) - \boldsymbol{\lambda}:(\mathbf{F} - \mathbf{F}_0) - \mathbf{P}_0:\mathbf{F}
58    /// ```
59    fn minimize(
60        &self,
61        applied_load: AppliedLoad,
62        solver: impl FirstOrderOptimization<Scalar, DeformationGradient>,
63    ) -> Result<DeformationGradient, ConstitutiveError>;
64}
65
66/// Second-order minimization methods for elastic solid constitutive models.
67pub trait SecondOrderMinimize {
68    /// Solve for the unknown components of the deformation gradient under an applied load.
69    ///
70    /// ```math
71    /// \Pi(\mathbf{F},\boldsymbol{\lambda}) = a(\mathbf{F}) - \boldsymbol{\lambda}:(\mathbf{F} - \mathbf{F}_0) - \mathbf{P}_0:\mathbf{F}
72    /// ```
73    fn minimize(
74        &self,
75        applied_load: AppliedLoad,
76        solver: impl SecondOrderOptimization<
77            Scalar,
78            FirstPiolaKirchhoffStress,
79            FirstPiolaKirchhoffTangentStiffness,
80            DeformationGradient,
81        >,
82    ) -> Result<DeformationGradient, ConstitutiveError>;
83}
84
85impl<T> FirstOrderMinimize for T
86where
87    T: Hyperelastic,
88{
89    fn minimize(
90        &self,
91        applied_load: AppliedLoad,
92        solver: impl FirstOrderOptimization<Scalar, DeformationGradient>,
93    ) -> Result<DeformationGradient, ConstitutiveError> {
94        let (matrix, vector) = bcs(applied_load);
95        match solver.minimize(
96            |deformation_gradient: &DeformationGradient| {
97                Ok(self.helmholtz_free_energy_density(deformation_gradient)?)
98            },
99            |deformation_gradient: &DeformationGradient| {
100                Ok(self.first_piola_kirchhoff_stress(deformation_gradient)?)
101            },
102            DeformationGradient::identity(),
103            EqualityConstraint::Linear(matrix, vector),
104        ) {
105            Ok(deformation_gradient) => Ok(deformation_gradient),
106            Err(error) => Err(ConstitutiveError::Upstream(
107                format!("{error}"),
108                format!("{self:?}"),
109            )),
110        }
111    }
112}
113
114impl<T> SecondOrderMinimize for T
115where
116    T: Hyperelastic,
117{
118    fn minimize(
119        &self,
120        applied_load: AppliedLoad,
121        solver: impl SecondOrderOptimization<
122            Scalar,
123            FirstPiolaKirchhoffStress,
124            FirstPiolaKirchhoffTangentStiffness,
125            DeformationGradient,
126        >,
127    ) -> Result<DeformationGradient, ConstitutiveError> {
128        let (matrix, vector) = bcs(applied_load);
129        match solver.minimize(
130            |deformation_gradient: &DeformationGradient| {
131                Ok(self.helmholtz_free_energy_density(deformation_gradient)?)
132            },
133            |deformation_gradient: &DeformationGradient| {
134                Ok(self.first_piola_kirchhoff_stress(deformation_gradient)?)
135            },
136            |deformation_gradient: &DeformationGradient| {
137                Ok(self.first_piola_kirchhoff_tangent_stiffness(deformation_gradient)?)
138            },
139            DeformationGradient::identity(),
140            EqualityConstraint::Linear(matrix, vector),
141            None,
142        ) {
143            Ok(deformation_gradient) => Ok(deformation_gradient),
144            Err(error) => Err(ConstitutiveError::Upstream(
145                format!("{error}"),
146                format!("{self:?}"),
147            )),
148        }
149    }
150}