conspire/constitutive/solid/hyperelastic/gent/
mod.rs

1#[cfg(test)]
2mod test;
3
4use crate::{
5    constitutive::{
6        Constitutive, ConstitutiveError, Parameters,
7        solid::{Solid, TWO_THIRDS, elastic::Elastic, hyperelastic::Hyperelastic},
8    },
9    math::{IDENTITY, Rank2},
10    mechanics::{CauchyStress, CauchyTangentStiffness, Deformation, DeformationGradient, Scalar},
11};
12
13#[doc = include_str!("doc.md")]
14#[derive(Debug)]
15pub struct Gent<P> {
16    parameters: P,
17}
18
19impl<P> Gent<P>
20where
21    P: Parameters,
22{
23    /// Returns the extensibility.
24    pub fn extensibility(&self) -> &Scalar {
25        self.parameters.get(2)
26    }
27}
28
29impl<P> Constitutive<P> for Gent<P>
30where
31    P: Parameters,
32{
33    fn new(parameters: P) -> Self {
34        Self { parameters }
35    }
36}
37
38impl<P> Solid for Gent<P>
39where
40    P: Parameters,
41{
42    fn bulk_modulus(&self) -> &Scalar {
43        self.parameters.get(0)
44    }
45    fn shear_modulus(&self) -> &Scalar {
46        self.parameters.get(1)
47    }
48}
49
50impl<P> Elastic for Gent<P>
51where
52    P: Parameters,
53{
54    #[doc = include_str!("cauchy_stress.md")]
55    fn cauchy_stress(
56        &self,
57        deformation_gradient: &DeformationGradient,
58    ) -> Result<CauchyStress, ConstitutiveError> {
59        let jacobian = self.jacobian(deformation_gradient)?;
60        let isochoric_left_cauchy_green_deformation =
61            deformation_gradient.left_cauchy_green() / jacobian.powf(TWO_THIRDS);
62        let (
63            deviatoric_isochoric_left_cauchy_green_deformation,
64            isochoric_left_cauchy_green_deformation_trace,
65        ) = isochoric_left_cauchy_green_deformation.deviatoric_and_trace();
66        let denominator =
67            self.extensibility() - isochoric_left_cauchy_green_deformation_trace + 3.0;
68        if denominator <= 0.0 {
69            Err(ConstitutiveError::Custom(
70                "Maximum extensibility reached.".to_string(),
71                deformation_gradient.clone(),
72                format!("{:?}", &self),
73            ))
74        } else {
75            Ok((deviatoric_isochoric_left_cauchy_green_deformation
76                * self.shear_modulus()
77                * self.extensibility()
78                / jacobian)
79                / denominator
80                + IDENTITY * self.bulk_modulus() * 0.5 * (jacobian - 1.0 / jacobian))
81        }
82    }
83    #[doc = include_str!("cauchy_tangent_stiffness.md")]
84    fn cauchy_tangent_stiffness(
85        &self,
86        deformation_gradient: &DeformationGradient,
87    ) -> Result<CauchyTangentStiffness, ConstitutiveError> {
88        let jacobian = self.jacobian(deformation_gradient)?;
89        let inverse_transpose_deformation_gradient = deformation_gradient.inverse_transpose();
90        let isochoric_left_cauchy_green_deformation =
91            deformation_gradient.left_cauchy_green() / jacobian.powf(TWO_THIRDS);
92        let (
93            deviatoric_isochoric_left_cauchy_green_deformation,
94            isochoric_left_cauchy_green_deformation_trace,
95        ) = isochoric_left_cauchy_green_deformation.deviatoric_and_trace();
96        let denominator =
97            self.extensibility() - isochoric_left_cauchy_green_deformation_trace + 3.0;
98        if denominator <= 0.0 {
99            Err(ConstitutiveError::Custom(
100                "Maximum extensibility reached.".to_string(),
101                deformation_gradient.clone(),
102                format!("{:?}", &self),
103            ))
104        } else {
105            let prefactor = self.shear_modulus() * self.extensibility() / jacobian / denominator;
106            Ok(
107                (CauchyTangentStiffness::dyad_ik_jl(&IDENTITY, deformation_gradient)
108                    + CauchyTangentStiffness::dyad_il_jk(deformation_gradient, &IDENTITY)
109                    - CauchyTangentStiffness::dyad_ij_kl(&IDENTITY, deformation_gradient)
110                        * (TWO_THIRDS)
111                    + CauchyTangentStiffness::dyad_ij_kl(
112                        &deviatoric_isochoric_left_cauchy_green_deformation,
113                        deformation_gradient,
114                    ) * (2.0 / denominator))
115                    * (prefactor / jacobian.powf(TWO_THIRDS))
116                    + CauchyTangentStiffness::dyad_ij_kl(
117                        &(IDENTITY * (0.5 * self.bulk_modulus() * (jacobian + 1.0 / jacobian))
118                            - deviatoric_isochoric_left_cauchy_green_deformation
119                                * prefactor
120                                * ((5.0
121                                    + 2.0 * isochoric_left_cauchy_green_deformation_trace
122                                        / denominator)
123                                    / 3.0)),
124                        &inverse_transpose_deformation_gradient,
125                    ),
126            )
127        }
128    }
129}
130
131impl<P> Hyperelastic for Gent<P>
132where
133    P: Parameters,
134{
135    #[doc = include_str!("helmholtz_free_energy_density.md")]
136    fn helmholtz_free_energy_density(
137        &self,
138        deformation_gradient: &DeformationGradient,
139    ) -> Result<Scalar, ConstitutiveError> {
140        let jacobian = self.jacobian(deformation_gradient)?;
141        let factor = (deformation_gradient.left_cauchy_green().trace() / jacobian.powf(TWO_THIRDS)
142            - 3.0)
143            / self.extensibility();
144        if factor >= 1.0 {
145            Err(ConstitutiveError::Custom(
146                "Maximum extensibility reached.".to_string(),
147                deformation_gradient.clone(),
148                format!("{:?}", &self),
149            ))
150        } else {
151            Ok(0.5
152                * (-self.shear_modulus() * self.extensibility() * (1.0 - factor).ln()
153                    + self.bulk_modulus() * (0.5 * (jacobian.powi(2) - 1.0) - jacobian.ln())))
154        }
155    }
156}