conspire/constitutive/solid/elastic_hyperviscous/almansi_hamel/
mod.rs

1#[cfg(test)]
2mod test;
3
4use super::*;
5
6/// The Almansi-Hamel viscoelastic 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 Almansi-Hamel strain measure is given by $`\mathbf{e}=\tfrac{1}{2}(\mathbf{1}-\mathbf{B}^{-1})`$.
23#[derive(Debug)]
24pub struct AlmansiHamel<P> {
25    parameters: P,
26}
27
28impl<P> Constitutive<P> for AlmansiHamel<P>
29where
30    P: Parameters,
31{
32    fn new(parameters: P) -> Self {
33        Self { parameters }
34    }
35}
36
37impl<P> Solid for AlmansiHamel<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 AlmansiHamel<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 AlmansiHamel<P>
62where
63    P: Parameters,
64{
65    /// Calculates and returns the Cauchy stress.
66    ///
67    /// ```math
68    /// \boldsymbol{\sigma}(\mathbf{F},\dot\mathbf{F}) = 2\mu\mathbf{e}' + \kappa\,\mathrm{tr}(\mathbf{e})\mathbf{1} + 2\eta\mathbf{D}' + \zeta\,\mathrm{tr}(\mathbf{D})\mathbf{1}
69    /// ```
70    fn cauchy_stress(
71        &self,
72        deformation_gradient: &DeformationGradient,
73        deformation_gradient_rate: &DeformationGradientRate,
74    ) -> Result<CauchyStress, ConstitutiveError> {
75        let jacobian = self.jacobian(deformation_gradient)?;
76        let inverse_deformation_gradient = deformation_gradient.inverse();
77        let strain = (IDENTITY
78            - inverse_deformation_gradient.transpose() * &inverse_deformation_gradient)
79            * 0.5;
80        let (deviatoric_strain, strain_trace) = strain.deviatoric_and_trace();
81        let velocity_gradient = deformation_gradient_rate * inverse_deformation_gradient;
82        let strain_rate = (&velocity_gradient + velocity_gradient.transpose()) * 0.5;
83        let (deviatoric_strain_rate, strain_rate_trace) = strain_rate.deviatoric_and_trace();
84        Ok(deviatoric_strain * (2.0 * self.shear_modulus() / jacobian)
85            + deviatoric_strain_rate * (2.0 * self.shear_viscosity() / jacobian)
86            + IDENTITY
87                * ((self.bulk_modulus() * strain_trace
88                    + self.bulk_viscosity() * strain_rate_trace)
89                    / jacobian))
90    }
91    /// Calculates and returns the rate tangent stiffness associated with the Cauchy stress.
92    ///
93    /// ```math
94    /// \mathcal{V}_{IJkL}(\mathbf{F}) = \eta\,\delta_{ik}F_{jL}^{-T} + \eta\,\delta_{jk}F_{iL}^{-T} + \left(\zeta - \frac{2}{3}\,\eta\right)\delta_{ij}F_{kL}^{-T}
95    /// ```
96    fn cauchy_rate_tangent_stiffness(
97        &self,
98        deformation_gradient: &DeformationGradient,
99        _: &DeformationGradientRate,
100    ) -> Result<CauchyRateTangentStiffness, ConstitutiveError> {
101        let jacobian = self.jacobian(deformation_gradient)?;
102        let deformation_gradient_inverse_transpose = deformation_gradient.inverse_transpose();
103        let scaled_deformation_gradient_inverse_transpose =
104            &deformation_gradient_inverse_transpose * self.shear_viscosity() / jacobian;
105        Ok(CauchyRateTangentStiffness::dyad_ik_jl(
106            &IDENTITY,
107            &scaled_deformation_gradient_inverse_transpose,
108        ) + CauchyRateTangentStiffness::dyad_il_jk(
109            &scaled_deformation_gradient_inverse_transpose,
110            &IDENTITY,
111        ) + CauchyRateTangentStiffness::dyad_ij_kl(
112            &(IDENTITY
113                * ((self.bulk_viscosity() - TWO_THIRDS * self.shear_viscosity()) / jacobian)),
114            &deformation_gradient_inverse_transpose,
115        ))
116    }
117}
118
119impl<P> ElasticHyperviscous for AlmansiHamel<P>
120where
121    P: Parameters,
122{
123    /// Calculates and returns the viscous dissipation.
124    ///
125    /// ```math
126    /// \phi(\mathbf{F},\dot{\mathbf{F}}) = \eta\,\mathrm{tr}(\mathbf{D}^2) + \frac{1}{2}\left(\zeta - \frac{2}{3}\,\eta\right)\mathrm{tr}(\mathbf{D})^2
127    /// ```
128    fn viscous_dissipation(
129        &self,
130        deformation_gradient: &DeformationGradient,
131        deformation_gradient_rate: &DeformationGradientRate,
132    ) -> Result<Scalar, ConstitutiveError> {
133        let _jacobian = self.jacobian(deformation_gradient)?;
134        let velocity_gradient = deformation_gradient_rate * deformation_gradient.inverse();
135        let strain_rate = (&velocity_gradient + velocity_gradient.transpose()) * 0.5;
136        Ok(self.shear_viscosity() * strain_rate.squared_trace()
137            + 0.5
138                * (self.bulk_viscosity() - TWO_THIRDS * self.shear_viscosity())
139                * strain_rate.trace().powi(2))
140    }
141}