Skip to main content

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

1#[cfg(test)]
2mod test;
3use crate::math::{Quantity, TensorRank4};
4use crate::units::{EnergyDensity, ReciprocalTemperature, Stress, Temperature};
5
6use super::*;
7
8#[doc = include_str!("doc.md")]
9#[derive(Clone, Debug)]
10pub struct SaintVenantKirchhoff {
11    /// The bulk modulus $`\kappa`$.
12    pub bulk_modulus: Quantity<Stress>,
13    /// The shear modulus $`\mu`$.
14    pub shear_modulus: Quantity<Stress>,
15    /// The coefficient of thermal expansion $`\alpha`$.
16    pub coefficient_of_thermal_expansion: Quantity<ReciprocalTemperature>,
17    /// The reference temperature $`T_\mathrm{ref}`$.
18    pub reference_temperature: Quantity<Temperature>,
19}
20
21impl Solid for SaintVenantKirchhoff {
22    fn bulk_modulus(&self) -> Quantity<Stress> {
23        self.bulk_modulus
24    }
25    fn shear_modulus(&self) -> Quantity<Stress> {
26        self.shear_modulus
27    }
28}
29
30impl Thermoelastic for SaintVenantKirchhoff {
31    #[doc = include_str!("second_piola_kirchhoff_stress.md")]
32    fn second_piola_kirchhoff_stress(
33        &self,
34        deformation_gradient: &DeformationGradient,
35        temperature: Quantity<Temperature>,
36    ) -> Result<SecondPiolaKirchhoffStress, ConstitutiveError> {
37        let _jacobian = self.jacobian(deformation_gradient)?;
38        let (deviatoric_strain, strain_trace) =
39            ((deformation_gradient.right_cauchy_green() - IDENTITY_00) * 0.5)
40                .deviatoric_and_trace();
41        Ok(deviatoric_strain * (2.0 * self.shear_modulus())
42            + IDENTITY_00
43                * (self.bulk_modulus()
44                    * (strain_trace
45                        - 3.0
46                            * self.coefficient_of_thermal_expansion()
47                            * (temperature - self.reference_temperature()))))
48    }
49    #[doc = include_str!("second_piola_kirchhoff_tangent_stiffness.md")]
50    fn second_piola_kirchhoff_tangent_stiffness(
51        &self,
52        deformation_gradient: &DeformationGradient,
53        _: Quantity<Temperature>,
54    ) -> Result<SecondPiolaKirchhoffTangentStiffness, ConstitutiveError> {
55        let _jacobian = self.jacobian(deformation_gradient)?;
56        let scaled_deformation_gradient_transpose =
57            deformation_gradient.transpose() * self.shear_modulus();
58        Ok(
59            TensorRank4::dyad_ik_jl(&scaled_deformation_gradient_transpose, &IDENTITY_00)
60                + TensorRank4::dyad_il_jk(&IDENTITY_00, &scaled_deformation_gradient_transpose)
61                + TensorRank4::dyad_ij_kl(
62                    &(IDENTITY_00 * (self.bulk_modulus() - TWO_THIRDS * self.shear_modulus())),
63                    deformation_gradient,
64                ),
65        )
66    }
67    fn coefficient_of_thermal_expansion(&self) -> Quantity<ReciprocalTemperature> {
68        self.coefficient_of_thermal_expansion
69    }
70    fn reference_temperature(&self) -> Quantity<Temperature> {
71        self.reference_temperature
72    }
73}
74
75impl Thermohyperelastic for SaintVenantKirchhoff {
76    #[doc = include_str!("helmholtz_free_energy_density.md")]
77    fn helmholtz_free_energy_density(
78        &self,
79        deformation_gradient: &DeformationGradient,
80        temperature: Quantity<Temperature>,
81    ) -> Result<Quantity<EnergyDensity>, ConstitutiveError> {
82        let _jacobian = self.jacobian(deformation_gradient)?;
83        let strain = (deformation_gradient.right_cauchy_green() - IDENTITY_00) * 0.5;
84        let strain_trace = strain.trace();
85        Ok(self.shear_modulus() * strain.squared_trace()
86            + 0.5
87                * (self.bulk_modulus() - TWO_THIRDS * self.shear_modulus())
88                * strain_trace.powi(2)
89            - 3.0
90                * self.bulk_modulus()
91                * self.coefficient_of_thermal_expansion()
92                * (temperature - self.reference_temperature())
93                * strain_trace)
94    }
95}