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

1#[cfg(test)]
2mod test;
3
4use crate::{
5    constitutive::{
6        ConstitutiveError,
7        fluid::{
8            plastic::Plastic,
9            viscoplastic::{Viscoplastic, ViscoplasticStateVariables, default_plastic_evolution},
10        },
11        solid::{
12            Solid, TWO_THIRDS,
13            elastic_viscoplastic::{ElasticPlasticOrViscoplastic, ElasticViscoplastic},
14            hyperelastic_viscoplastic::HyperelasticViscoplastic,
15        },
16    },
17    math::{IDENTITY_22, Rank2, TensorArray},
18    mechanics::{
19        Deformation, DeformationGradient, DeformationGradientPlastic, MandelStressElastic, Scalar,
20        SecondPiolaKirchhoffStress, SecondPiolaKirchhoffTangentStiffness,
21    },
22};
23
24#[doc = include_str!("doc.md")]
25#[derive(Clone, Debug)]
26pub struct SaintVenantKirchhoff {
27    /// The bulk modulus $`\kappa`$.
28    pub bulk_modulus: Scalar,
29    /// The shear modulus $`\mu`$.
30    pub shear_modulus: Scalar,
31    /// The initial yield stress $`Y_0`$.
32    pub yield_stress: Scalar,
33    /// The isotropic hardening slope $`H`$.
34    pub hardening_slope: Scalar,
35    /// The rate sensitivity parameter $`m`$.
36    pub rate_sensitivity: Scalar,
37    /// The reference flow rate $`d_0`$.
38    pub reference_flow_rate: Scalar,
39}
40
41impl Solid for SaintVenantKirchhoff {
42    fn bulk_modulus(&self) -> Scalar {
43        self.bulk_modulus
44    }
45    fn shear_modulus(&self) -> Scalar {
46        self.shear_modulus
47    }
48}
49
50impl Plastic for SaintVenantKirchhoff {
51    fn initial_yield_stress(&self) -> Scalar {
52        self.yield_stress
53    }
54    fn hardening_slope(&self) -> Scalar {
55        self.hardening_slope
56    }
57}
58
59impl Viscoplastic<Scalar> for SaintVenantKirchhoff {
60    fn initial_state(&self) -> ViscoplasticStateVariables<Scalar> {
61        (DeformationGradientPlastic::identity(), 0.0).into()
62    }
63    fn plastic_evolution(
64        &self,
65        mandel_stress: MandelStressElastic,
66        state_variables: &ViscoplasticStateVariables<Scalar>,
67    ) -> Result<ViscoplasticStateVariables<Scalar>, ConstitutiveError> {
68        default_plastic_evolution(self, mandel_stress, state_variables)
69    }
70    fn rate_sensitivity(&self) -> Scalar {
71        self.rate_sensitivity
72    }
73    fn reference_flow_rate(&self) -> Scalar {
74        self.reference_flow_rate
75    }
76}
77
78impl ElasticPlasticOrViscoplastic for SaintVenantKirchhoff {
79    #[doc = include_str!("second_piola_kirchhoff_stress.md")]
80    fn second_piola_kirchhoff_stress(
81        &self,
82        deformation_gradient: &DeformationGradient,
83        deformation_gradient_p: &DeformationGradientPlastic,
84    ) -> Result<SecondPiolaKirchhoffStress, ConstitutiveError> {
85        let _jacobian = self.jacobian(deformation_gradient)?;
86        let deformation_gradient_inverse_p = deformation_gradient_p.inverse();
87        let deformation_gradient_e = deformation_gradient * &deformation_gradient_inverse_p;
88        let left_cauchy_green_inverse_p = deformation_gradient_inverse_p.left_cauchy_green();
89        let (deviatoric_strain, strain_trace) =
90            ((deformation_gradient_e.right_cauchy_green() - IDENTITY_22) * 0.5)
91                .deviatoric_and_trace();
92        Ok(&deformation_gradient_inverse_p
93            * deviatoric_strain
94            * deformation_gradient_inverse_p.transpose()
95            * (2.0 * self.shear_modulus())
96            + left_cauchy_green_inverse_p * (self.bulk_modulus() * strain_trace))
97    }
98    #[doc = include_str!("second_piola_kirchhoff_tangent_stiffness.md")]
99    fn second_piola_kirchhoff_tangent_stiffness(
100        &self,
101        deformation_gradient: &DeformationGradient,
102        deformation_gradient_p: &DeformationGradientPlastic,
103    ) -> Result<SecondPiolaKirchhoffTangentStiffness, ConstitutiveError> {
104        let _jacobian = self.jacobian(deformation_gradient)?;
105        let deformation_gradient_inverse_p = deformation_gradient_p.inverse();
106        let deformation_gradient_e = deformation_gradient * &deformation_gradient_inverse_p;
107        let quantity_1 = deformation_gradient_inverse_p.left_cauchy_green();
108        let quantity_2 = deformation_gradient_inverse_p * deformation_gradient_e.transpose();
109        let scaled_quantity_1 = &quantity_1 * self.shear_modulus();
110        Ok(
111            (SecondPiolaKirchhoffTangentStiffness::dyad_ik_jl(&quantity_2, &scaled_quantity_1)
112                + SecondPiolaKirchhoffTangentStiffness::dyad_il_jk(
113                    &scaled_quantity_1,
114                    &quantity_2,
115                ))
116                + SecondPiolaKirchhoffTangentStiffness::dyad_ij_kl(
117                    &(quantity_1 * (self.bulk_modulus() - TWO_THIRDS * self.shear_modulus())),
118                    &quantity_2.transpose(),
119                ),
120        )
121    }
122}
123
124impl ElasticViscoplastic<Scalar> for SaintVenantKirchhoff {}
125
126impl HyperelasticViscoplastic<Scalar> for SaintVenantKirchhoff {
127    #[doc = include_str!("helmholtz_free_energy_density.md")]
128    fn helmholtz_free_energy_density(
129        &self,
130        deformation_gradient: &DeformationGradient,
131        deformation_gradient_p: &DeformationGradientPlastic,
132    ) -> Result<Scalar, ConstitutiveError> {
133        let _jacobian = self.jacobian(deformation_gradient)?;
134        let deformation_gradient_e = deformation_gradient * deformation_gradient_p.inverse();
135        let strain = (deformation_gradient_e.right_cauchy_green() - IDENTITY_22) * 0.5;
136        Ok(self.shear_modulus() * strain.squared_trace()
137            + 0.5
138                * (self.bulk_modulus() - TWO_THIRDS * self.shear_modulus())
139                * strain.trace().powi(2))
140    }
141}