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

1#[cfg(test)]
2mod test;
3
4use super::*;
5
6/// The Saint Venant-Kirchhoff hyperviscoelastic constitutive model.
7///
8/// **Parameters**
9/// - The bulk modulus $`\kappa`$.
10/// - The shear modulus $`\mu`$.
11/// - The bulk viscosity $`\zeta`$.
12/// - The shear viscosity $`\eta`$.
13///
14/// **External variables**
15/// - The deformation gradient $`\mathbf{F}`$.
16/// - The deformation gradient rate $`\dot{\mathbf{F}}`$.
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> Viscous for SaintVenantKirchhoff<P>
50where
51    P: Parameters,
52{
53    fn bulk_viscosity(&self) -> &Scalar {
54        self.parameters.get(2)
55    }
56    fn shear_viscosity(&self) -> &Scalar {
57        self.parameters.get(3)
58    }
59}
60
61impl<P> Viscoelastic for SaintVenantKirchhoff<P>
62where
63    P: Parameters,
64{
65    /// Calculates and returns the second Piola-Kirchhoff stress.
66    ///
67    /// ```math
68    /// \mathbf{S}(\mathbf{F},\dot\mathbf{F}) = 2\mu\mathbf{E}' + \kappa\,\mathrm{tr}(\mathbf{E})\mathbf{1} + 2\eta\dot{\mathbf{E}}' + \zeta\,\mathrm{tr}(\dot{\mathbf{E}})\mathbf{1}
69    /// ```
70    fn second_piola_kirchhoff_stress(
71        &self,
72        deformation_gradient: &DeformationGradient,
73        deformation_gradient_rate: &DeformationGradientRate,
74    ) -> Result<SecondPiolaKirchhoffStress, ConstitutiveError> {
75        let _jacobian = self.jacobian(deformation_gradient)?;
76        let (deviatoric_strain, strain_trace) =
77            ((deformation_gradient.right_cauchy_green() - IDENTITY_00) * 0.5)
78                .deviatoric_and_trace();
79        let first_term = deformation_gradient_rate.transpose() * deformation_gradient;
80        let (deviatoric_strain_rate, strain_rate_trace) =
81            ((&first_term + first_term.transpose()) * 0.5).deviatoric_and_trace();
82        Ok(deviatoric_strain * (2.0 * self.shear_modulus())
83            + deviatoric_strain_rate * (2.0 * self.shear_viscosity())
84            + IDENTITY_00
85                * (self.bulk_modulus() * strain_trace + self.bulk_viscosity() * strain_rate_trace))
86    }
87    /// Calculates and returns the rate tangent stiffness associated with the second Piola-Kirchhoff stress.
88    ///
89    /// ```math
90    /// \mathcal{W}_{IJkL}(\mathbf{F}) = \eta\,\delta_{JL}F_{kI} + \eta\,\delta_{IL}F_{kJ} + \left(\zeta - \frac{2}{3}\,\eta\right)\delta_{IJ}F_{kL}
91    /// ```
92    fn second_piola_kirchhoff_rate_tangent_stiffness(
93        &self,
94        deformation_gradient: &DeformationGradient,
95        _: &DeformationGradientRate,
96    ) -> Result<SecondPiolaKirchhoffRateTangentStiffness, ConstitutiveError> {
97        let _jacobian = self.jacobian(deformation_gradient)?;
98        let scaled_deformation_gradient_transpose =
99            deformation_gradient.transpose() * self.shear_viscosity();
100        Ok(SecondPiolaKirchhoffRateTangentStiffness::dyad_ik_jl(
101            &scaled_deformation_gradient_transpose,
102            &IDENTITY_00,
103        ) + SecondPiolaKirchhoffRateTangentStiffness::dyad_il_jk(
104            &IDENTITY_00,
105            &scaled_deformation_gradient_transpose,
106        ) + SecondPiolaKirchhoffRateTangentStiffness::dyad_ij_kl(
107            &(IDENTITY_00 * (self.bulk_viscosity() - TWO_THIRDS * self.shear_viscosity())),
108            deformation_gradient,
109        ))
110    }
111}
112
113impl<P> ElasticHyperviscous for SaintVenantKirchhoff<P>
114where
115    P: Parameters,
116{
117    /// Calculates and returns the viscous dissipation.
118    ///
119    /// ```math
120    /// \phi(\mathbf{F},\dot{\mathbf{F}}) = \eta\,\mathrm{tr}(\dot{\mathbf{E}}^2) + \frac{1}{2}\left(\zeta - \frac{2}{3}\,\eta\right)\mathrm{tr}(\dot{\mathbf{E}})^2
121    /// ```
122    fn viscous_dissipation(
123        &self,
124        deformation_gradient: &DeformationGradient,
125        deformation_gradient_rate: &DeformationGradientRate,
126    ) -> Result<Scalar, ConstitutiveError> {
127        let _jacobian = self.jacobian(deformation_gradient)?;
128        let first_term = deformation_gradient_rate.transpose() * deformation_gradient;
129        let strain_rate = (&first_term + first_term.transpose()) * 0.5;
130        Ok(self.shear_viscosity() * strain_rate.squared_trace()
131            + 0.5
132                * (self.bulk_viscosity() - TWO_THIRDS * self.shear_viscosity())
133                * strain_rate.trace().powi(2))
134    }
135}
136
137impl<P> Hyperviscoelastic for SaintVenantKirchhoff<P>
138where
139    P: Parameters,
140{
141    /// Calculates and returns the Helmholtz free energy density.
142    ///
143    /// ```math
144    /// a(\mathbf{F}) = \mu\,\mathrm{tr}(\mathbf{E}^2) + \frac{1}{2}\left(\kappa - \frac{2}{3}\,\mu\right)\mathrm{tr}(\mathbf{E})^2
145    /// ```
146    fn helmholtz_free_energy_density(
147        &self,
148        deformation_gradient: &DeformationGradient,
149    ) -> Result<Scalar, ConstitutiveError> {
150        let _jacobian = self.jacobian(deformation_gradient)?;
151        let strain = (deformation_gradient.right_cauchy_green() - IDENTITY_00) * 0.5;
152        Ok(self.shear_modulus() * strain.squared_trace()
153            + 0.5
154                * (self.bulk_modulus() - TWO_THIRDS * self.shear_modulus())
155                * strain.trace().powi(2))
156    }
157}