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

1#[cfg(test)]
2mod test;
3
4use crate::{
5    constitutive::{
6        Constitutive, ConstitutiveError, Parameters,
7        solid::{FIVE_THIRDS, 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 MooneyRivlin<P> {
16    parameters: P,
17}
18
19impl<P> MooneyRivlin<P>
20where
21    P: Parameters,
22{
23    /// Returns the extra modulus.
24    pub fn extra_modulus(&self) -> &Scalar {
25        self.parameters.get(2)
26    }
27}
28
29impl<P> Constitutive<P> for MooneyRivlin<P>
30where
31    P: Parameters,
32{
33    fn new(parameters: P) -> Self {
34        Self { parameters }
35    }
36}
37
38impl<P> Solid for MooneyRivlin<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 MooneyRivlin<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        Ok(((isochoric_left_cauchy_green_deformation.deviatoric()
63            * (self.shear_modulus() - self.extra_modulus())
64            - isochoric_left_cauchy_green_deformation
65                .inverse()
66                .deviatoric()
67                * self.extra_modulus())
68            + IDENTITY * (self.bulk_modulus() * 0.5 * (jacobian.powi(2) - 1.0)))
69            / jacobian)
70    }
71    #[doc = include_str!("cauchy_tangent_stiffness.md")]
72    fn cauchy_tangent_stiffness(
73        &self,
74        deformation_gradient: &DeformationGradient,
75    ) -> Result<CauchyTangentStiffness, ConstitutiveError> {
76        let jacobian = self.jacobian(deformation_gradient)?;
77        let inverse_transpose_deformation_gradient = deformation_gradient.inverse_transpose();
78        let scaled_delta_shear_modulus =
79            (self.shear_modulus() - self.extra_modulus()) / jacobian.powf(FIVE_THIRDS);
80        let inverse_isochoric_left_cauchy_green_deformation =
81            (deformation_gradient.left_cauchy_green() / jacobian.powf(TWO_THIRDS)).inverse();
82        let deviatoric_inverse_isochoric_left_cauchy_green_deformation =
83            inverse_isochoric_left_cauchy_green_deformation.deviatoric();
84        let term_1 = CauchyTangentStiffness::dyad_ij_kl(
85            &inverse_isochoric_left_cauchy_green_deformation,
86            &inverse_transpose_deformation_gradient,
87        ) * TWO_THIRDS
88            - CauchyTangentStiffness::dyad_ik_jl(
89                &inverse_isochoric_left_cauchy_green_deformation,
90                &inverse_transpose_deformation_gradient,
91            )
92            - CauchyTangentStiffness::dyad_il_jk(
93                &inverse_transpose_deformation_gradient,
94                &inverse_isochoric_left_cauchy_green_deformation,
95            );
96        let term_3 = CauchyTangentStiffness::dyad_ij_kl(
97            &deviatoric_inverse_isochoric_left_cauchy_green_deformation,
98            &inverse_transpose_deformation_gradient,
99        );
100        let term_2 = CauchyTangentStiffness::dyad_ij_kl(
101            &IDENTITY,
102            &((deviatoric_inverse_isochoric_left_cauchy_green_deformation * TWO_THIRDS)
103                * &inverse_transpose_deformation_gradient),
104        );
105        Ok(
106            (CauchyTangentStiffness::dyad_ik_jl(&IDENTITY, deformation_gradient)
107                + CauchyTangentStiffness::dyad_il_jk(deformation_gradient, &IDENTITY)
108                - CauchyTangentStiffness::dyad_ij_kl(&IDENTITY, deformation_gradient)
109                    * (TWO_THIRDS))
110                * scaled_delta_shear_modulus
111                + CauchyTangentStiffness::dyad_ij_kl(
112                    &(IDENTITY * (0.5 * self.bulk_modulus() * (jacobian + 1.0 / jacobian))
113                        - deformation_gradient.left_cauchy_green().deviatoric()
114                            * (scaled_delta_shear_modulus * FIVE_THIRDS)),
115                    &inverse_transpose_deformation_gradient,
116                )
117                - (term_1 + term_2 - term_3) * self.extra_modulus() / jacobian,
118        )
119    }
120}
121
122impl<P> Hyperelastic for MooneyRivlin<P>
123where
124    P: Parameters,
125{
126    #[doc = include_str!("helmholtz_free_energy_density.md")]
127    fn helmholtz_free_energy_density(
128        &self,
129        deformation_gradient: &DeformationGradient,
130    ) -> Result<Scalar, ConstitutiveError> {
131        let jacobian = self.jacobian(deformation_gradient)?;
132        let isochoric_left_cauchy_green_deformation =
133            deformation_gradient.left_cauchy_green() / jacobian.powf(TWO_THIRDS);
134        Ok(0.5
135            * ((self.shear_modulus() - self.extra_modulus())
136                * (isochoric_left_cauchy_green_deformation.trace() - 3.0)
137                + self.extra_modulus()
138                    * (isochoric_left_cauchy_green_deformation.second_invariant() - 3.0)
139                + self.bulk_modulus() * (0.5 * (jacobian.powi(2) - 1.0) - jacobian.ln())))
140    }
141}