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