Skip to main content

conspire/constitutive/solid/elastic_viscoplastic/almansi_hamel_eulerian/
mod.rs

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