Skip to main content

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

1#[cfg(test)]
2mod test;
3
4use crate::{
5    constitutive::{
6        ConstitutiveError,
7        solid::{Solid, TWO_THIRDS, elastic::Elastic, hyperelastic::Hyperelastic},
8    },
9    math::{IDENTITY_00, Quantity, Rank2, TensorRank4},
10    mechanics::{
11        Deformation, DeformationGradient, SecondPiolaKirchhoffStress,
12        SecondPiolaKirchhoffTangentStiffness,
13    },
14    units::{EnergyDensity, Stress},
15};
16
17#[doc = include_str!("doc.md")]
18#[derive(Clone, Debug)]
19pub struct SaintVenantKirchhoff {
20    /// The bulk modulus $`\kappa`$.
21    pub bulk_modulus: Quantity<Stress>,
22    /// The shear modulus $`\mu`$.
23    pub shear_modulus: Quantity<Stress>,
24}
25
26impl Solid for SaintVenantKirchhoff {
27    fn bulk_modulus(&self) -> Quantity<Stress> {
28        self.bulk_modulus
29    }
30    fn shear_modulus(&self) -> Quantity<Stress> {
31        self.shear_modulus
32    }
33}
34
35impl Elastic for SaintVenantKirchhoff {
36    #[doc = include_str!("second_piola_kirchhoff_stress.md")]
37    fn second_piola_kirchhoff_stress(
38        &self,
39        deformation_gradient: &DeformationGradient,
40    ) -> Result<SecondPiolaKirchhoffStress, ConstitutiveError> {
41        let _jacobian = self.jacobian(deformation_gradient)?;
42        let (deviatoric_strain, strain_trace) =
43            ((deformation_gradient.right_cauchy_green() - IDENTITY_00) * 0.5)
44                .deviatoric_and_trace();
45        Ok(deviatoric_strain * (2.0 * self.shear_modulus())
46            + IDENTITY_00 * (self.bulk_modulus() * strain_trace))
47    }
48    #[doc = include_str!("second_piola_kirchhoff_tangent_stiffness.md")]
49    fn second_piola_kirchhoff_tangent_stiffness(
50        &self,
51        deformation_gradient: &DeformationGradient,
52    ) -> Result<SecondPiolaKirchhoffTangentStiffness, ConstitutiveError> {
53        let _jacobian = self.jacobian(deformation_gradient)?;
54        let scaled_deformation_gradient_transpose =
55            deformation_gradient.transpose() * self.shear_modulus();
56        Ok(
57            TensorRank4::dyad_ik_jl(&scaled_deformation_gradient_transpose, &IDENTITY_00)
58                + TensorRank4::dyad_il_jk(&IDENTITY_00, &scaled_deformation_gradient_transpose)
59                + TensorRank4::dyad_ij_kl(
60                    &(IDENTITY_00 * (self.bulk_modulus() - TWO_THIRDS * self.shear_modulus())),
61                    deformation_gradient,
62                ),
63        )
64    }
65}
66
67impl Hyperelastic for SaintVenantKirchhoff {
68    #[doc = include_str!("helmholtz_free_energy_density.md")]
69    fn helmholtz_free_energy_density(
70        &self,
71        deformation_gradient: &DeformationGradient,
72    ) -> Result<Quantity<EnergyDensity>, ConstitutiveError> {
73        let _jacobian = self.jacobian(deformation_gradient)?;
74        let strain = (deformation_gradient.right_cauchy_green() - IDENTITY_00) * 0.5;
75        Ok(self.shear_modulus() * strain.squared_trace()
76            + 0.5
77                * (self.bulk_modulus() - TWO_THIRDS * self.shear_modulus())
78                * strain.trace().powi(2))
79    }
80}