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

1#[cfg(test)]
2mod test;
3
4use super::*;
5
6/// The Saint Venant-Kirchhoff thermohyperelastic constitutive model.
7///
8/// **Parameters**
9/// - The bulk modulus $`\kappa`$.
10/// - The shear modulus $`\mu`$.
11/// - The coefficient of thermal expansion $`\alpha`$.
12/// - The reference temperature $`T_\mathrm{ref}`$.
13///
14/// **External variables**
15/// - The deformation gradient $`\mathbf{F}`$.
16/// - The temperature $`T`$.
17///
18/// **Internal variables**
19/// - None.
20///
21/// **Notes**
22/// - The Green-Saint Venant strain measure is given by $`\mathbf{E}=\tfrac{1}{2}(\mathbf{C}-\mathbf{1})`$.
23#[derive(Debug)]
24pub struct SaintVenantKirchhoff<P> {
25    parameters: P,
26}
27
28impl<P> Constitutive<P> for SaintVenantKirchhoff<P>
29where
30    P: Parameters,
31{
32    fn new(parameters: P) -> Self {
33        Self { parameters }
34    }
35}
36
37impl<P> Solid for SaintVenantKirchhoff<P>
38where
39    P: Parameters,
40{
41    fn bulk_modulus(&self) -> &Scalar {
42        self.parameters.get(0)
43    }
44    fn shear_modulus(&self) -> &Scalar {
45        self.parameters.get(1)
46    }
47}
48
49impl<P> Thermoelastic for SaintVenantKirchhoff<P>
50where
51    P: Parameters,
52{
53    /// Calculates and returns the second Piola-Kirchhoff stress.
54    ///
55    /// ```math
56    /// \mathbf{S}(\mathbf{F}, T) = 2\mu\mathbf{E}' + \kappa\,\mathrm{tr}(\mathbf{E})\mathbf{1} - 3\alpha\kappa(T - T_\mathrm{ref})\mathbf{1}
57    /// ```
58    fn second_piola_kirchhoff_stress(
59        &self,
60        deformation_gradient: &DeformationGradient,
61        temperature: &Scalar,
62    ) -> Result<SecondPiolaKirchhoffStress, ConstitutiveError> {
63        let _jacobian = self.jacobian(deformation_gradient)?;
64        let (deviatoric_strain, strain_trace) =
65            ((deformation_gradient.right_cauchy_green() - IDENTITY_00) * 0.5)
66                .deviatoric_and_trace();
67        Ok(deviatoric_strain * (2.0 * self.shear_modulus())
68            + IDENTITY_00
69                * (self.bulk_modulus()
70                    * (strain_trace
71                        - 3.0
72                            * self.coefficient_of_thermal_expansion()
73                            * (temperature - self.reference_temperature()))))
74    }
75    /// Calculates and returns the tangent stiffness associated with the second Piola-Kirchhoff stress.
76    ///
77    /// ```math
78    /// \mathcal{G}_{IJkL}(\mathbf{F}) = \mu\,\delta_{JL}F_{kI} + \mu\,\delta_{IL}F_{kJ} + \left(\kappa - \frac{2}{3}\,\mu\right)\delta_{IJ}F_{kL}
79    /// ```
80    fn second_piola_kirchhoff_tangent_stiffness(
81        &self,
82        deformation_gradient: &DeformationGradient,
83        _: &Scalar,
84    ) -> Result<SecondPiolaKirchhoffTangentStiffness, ConstitutiveError> {
85        let _jacobian = self.jacobian(deformation_gradient)?;
86        let scaled_deformation_gradient_transpose =
87            deformation_gradient.transpose() * self.shear_modulus();
88        Ok(SecondPiolaKirchhoffTangentStiffness::dyad_ik_jl(
89            &scaled_deformation_gradient_transpose,
90            &IDENTITY_00,
91        ) + SecondPiolaKirchhoffTangentStiffness::dyad_il_jk(
92            &IDENTITY_00,
93            &scaled_deformation_gradient_transpose,
94        ) + SecondPiolaKirchhoffTangentStiffness::dyad_ij_kl(
95            &(IDENTITY_00 * (self.bulk_modulus() - TWO_THIRDS * self.shear_modulus())),
96            deformation_gradient,
97        ))
98    }
99    fn coefficient_of_thermal_expansion(&self) -> &Scalar {
100        self.parameters.get(2)
101    }
102    fn reference_temperature(&self) -> &Scalar {
103        self.parameters.get(3)
104    }
105}
106
107impl<P> Thermohyperelastic for SaintVenantKirchhoff<P>
108where
109    P: Parameters,
110{
111    /// Calculates and returns the Helmholtz free energy density.
112    ///
113    /// ```math
114    /// a(\mathbf{F}, T) = \mu\,\mathrm{tr}(\mathbf{E}^2) + \frac{1}{2}\left(\kappa - \frac{2}{3}\,\mu\right)\mathrm{tr}(\mathbf{E})^2 - 3\alpha\kappa\,\mathrm{tr}(\mathbf{E})(T - T_\mathrm{ref})
115    /// ```
116    fn helmholtz_free_energy_density(
117        &self,
118        deformation_gradient: &DeformationGradient,
119        temperature: &Scalar,
120    ) -> Result<Scalar, ConstitutiveError> {
121        let _jacobian = self.jacobian(deformation_gradient)?;
122        let strain = (deformation_gradient.right_cauchy_green() - IDENTITY_00) * 0.5;
123        let strain_trace = strain.trace();
124        Ok(self.shear_modulus() * strain.squared_trace()
125            + 0.5
126                * (self.bulk_modulus() - TWO_THIRDS * self.shear_modulus())
127                * strain_trace.powi(2)
128            - 3.0
129                * self.bulk_modulus()
130                * self.coefficient_of_thermal_expansion()
131                * (temperature - self.reference_temperature())
132                * strain_trace)
133    }
134}