conspire/constitutive/solid/elastic_plastic/
mod.rs

1//! Elastic-plastic solid constitutive models.
2
3use crate::{
4    constitutive::{ConstitutiveError, fluid::plastic::Plastic, solid::Solid},
5    math::{
6        ContractFirstSecondIndicesWithSecondIndicesOf, ContractSecondIndexWithFirstIndexOf,
7        IDENTITY, Rank2,
8    },
9    mechanics::{
10        CauchyStress, CauchyTangentStiffness, DeformationGradient, DeformationGradientPlastic,
11        FirstPiolaKirchhoffStress, FirstPiolaKirchhoffTangentStiffness, Scalar,
12        SecondPiolaKirchhoffStress, SecondPiolaKirchhoffTangentStiffness,
13    },
14};
15
16/// Possible applied loads.
17pub enum AppliedLoad<'a> {
18    /// Uniaxial stress given $`F_{11}`$.
19    UniaxialStress(fn(Scalar) -> Scalar, &'a [Scalar]),
20    // /// Biaxial stress given $`F_{11}`$ and $`F_{22}`$.
21    // BiaxialStress(fn(Scalar) -> Scalar, fn(Scalar) -> Scalar, &'a [Scalar]),
22}
23
24/// Required methods for elastic-plastic or elastic-viscoplastic solid constitutive models.
25pub trait ElasticPlasticOrViscoplastic
26where
27    Self: Solid + Plastic,
28{
29    /// Calculates and returns the Cauchy stress.
30    ///
31    /// ```math
32    /// \boldsymbol{\sigma} = \boldsymbol{\sigma}_\mathrm{e}
33    /// ```
34    fn cauchy_stress(
35        &self,
36        deformation_gradient: &DeformationGradient,
37        deformation_gradient_p: &DeformationGradientPlastic,
38    ) -> Result<CauchyStress, ConstitutiveError> {
39        Ok(deformation_gradient
40            * self.second_piola_kirchhoff_stress(deformation_gradient, deformation_gradient_p)?
41            * deformation_gradient.transpose()
42            / deformation_gradient.determinant())
43    }
44    /// Calculates and returns the tangent stiffness associated with the Cauchy stress.
45    ///
46    /// ```math
47    /// \boldsymbol{\mathcal{T}} = \boldsymbol{\mathcal{T}}_\mathrm{e}\cdot\mathbf{F}_\mathrm{p}^{-T}
48    /// ```
49    fn cauchy_tangent_stiffness(
50        &self,
51        deformation_gradient: &DeformationGradient,
52        deformation_gradient_p: &DeformationGradientPlastic,
53    ) -> Result<CauchyTangentStiffness, ConstitutiveError> {
54        let deformation_gradient_inverse_transpose = deformation_gradient.inverse_transpose();
55        let cauchy_stress = self.cauchy_stress(deformation_gradient, deformation_gradient_p)?;
56        let some_stress = &cauchy_stress * &deformation_gradient_inverse_transpose;
57        Ok(self
58            .second_piola_kirchhoff_tangent_stiffness(deformation_gradient, deformation_gradient_p)?
59            .contract_first_second_indices_with_second_indices_of(
60                deformation_gradient,
61                deformation_gradient,
62            )
63            / deformation_gradient.determinant()
64            - CauchyTangentStiffness::dyad_ij_kl(
65                &cauchy_stress,
66                &deformation_gradient_inverse_transpose,
67            )
68            + CauchyTangentStiffness::dyad_il_kj(&some_stress, &IDENTITY)
69            + CauchyTangentStiffness::dyad_ik_jl(&IDENTITY, &some_stress))
70    }
71    /// Calculates and returns the first Piola-Kirchhoff stress.
72    ///
73    /// ```math
74    /// \mathbf{P} = \mathbf{P}_\mathrm{e}\cdot\mathbf{F}_\mathrm{p}^{-T}
75    /// ```
76    fn first_piola_kirchhoff_stress(
77        &self,
78        deformation_gradient: &DeformationGradient,
79        deformation_gradient_p: &DeformationGradientPlastic,
80    ) -> Result<FirstPiolaKirchhoffStress, ConstitutiveError> {
81        Ok(
82            self.cauchy_stress(deformation_gradient, deformation_gradient_p)?
83                * deformation_gradient.inverse_transpose()
84                * deformation_gradient.determinant(),
85        )
86    }
87    /// Calculates and returns the tangent stiffness associated with the first Piola-Kirchhoff stress.
88    ///
89    /// ```math
90    /// \mathcal{C}_{iJkL} = \mathcal{C}^\mathrm{e}_{iMkN} F_{MJ}^{\mathrm{p}-T} F_{NL}^{\mathrm{p}-T}
91    /// ```
92    fn first_piola_kirchhoff_tangent_stiffness(
93        &self,
94        deformation_gradient: &DeformationGradient,
95        deformation_gradient_p: &DeformationGradientPlastic,
96    ) -> Result<FirstPiolaKirchhoffTangentStiffness, ConstitutiveError> {
97        let deformation_gradient_inverse_transpose = deformation_gradient.inverse_transpose();
98        let first_piola_kirchhoff_stress =
99            self.first_piola_kirchhoff_stress(deformation_gradient, deformation_gradient_p)?;
100        Ok(self
101            .cauchy_tangent_stiffness(deformation_gradient, deformation_gradient_p)?
102            .contract_second_index_with_first_index_of(&deformation_gradient_inverse_transpose)
103            * deformation_gradient.determinant()
104            + FirstPiolaKirchhoffTangentStiffness::dyad_ij_kl(
105                &first_piola_kirchhoff_stress,
106                &deformation_gradient_inverse_transpose,
107            )
108            - FirstPiolaKirchhoffTangentStiffness::dyad_il_kj(
109                &first_piola_kirchhoff_stress,
110                &deformation_gradient_inverse_transpose,
111            ))
112    }
113    /// Calculates and returns the second Piola-Kirchhoff stress.
114    ///
115    /// ```math
116    /// \mathbf{S} = \mathbf{F}_\mathrm{p}^{-1}\cdot\mathbf{S}_\mathrm{e}\cdot\mathbf{F}_\mathrm{p}^{-T}
117    /// ```
118    fn second_piola_kirchhoff_stress(
119        &self,
120        deformation_gradient: &DeformationGradient,
121        deformation_gradient_p: &DeformationGradientPlastic,
122    ) -> Result<SecondPiolaKirchhoffStress, ConstitutiveError> {
123        Ok(deformation_gradient.inverse()
124            * self.first_piola_kirchhoff_stress(deformation_gradient, deformation_gradient_p)?)
125    }
126    /// Calculates and returns the tangent stiffness associated with the second Piola-Kirchhoff stress.
127    ///
128    /// ```math
129    /// \mathcal{G}_{IJkL} = \mathcal{G}^\mathrm{e}_{MNkO} F_{MI}^{\mathrm{p}-T} F_{NJ}^{\mathrm{p}-T} F_{OL}^{\mathrm{p}-T}
130    /// ```
131    fn second_piola_kirchhoff_tangent_stiffness(
132        &self,
133        deformation_gradient: &DeformationGradient,
134        deformation_gradient_p: &DeformationGradientPlastic,
135    ) -> Result<SecondPiolaKirchhoffTangentStiffness, ConstitutiveError> {
136        let deformation_gradient_inverse_transpose = deformation_gradient.inverse_transpose();
137        let deformation_gradient_inverse = deformation_gradient_inverse_transpose.transpose();
138        let second_piola_kirchhoff_stress =
139            self.second_piola_kirchhoff_stress(deformation_gradient, deformation_gradient_p)?;
140        Ok(self
141            .cauchy_tangent_stiffness(deformation_gradient, deformation_gradient_p)?
142            .contract_first_second_indices_with_second_indices_of(
143                &deformation_gradient_inverse,
144                &deformation_gradient_inverse,
145            )
146            * deformation_gradient.determinant()
147            + SecondPiolaKirchhoffTangentStiffness::dyad_ij_kl(
148                &second_piola_kirchhoff_stress,
149                &deformation_gradient_inverse_transpose,
150            )
151            - SecondPiolaKirchhoffTangentStiffness::dyad_il_kj(
152                &second_piola_kirchhoff_stress,
153                &deformation_gradient_inverse_transpose,
154            )
155            - SecondPiolaKirchhoffTangentStiffness::dyad_ik_jl(
156                &deformation_gradient_inverse,
157                &second_piola_kirchhoff_stress,
158            ))
159    }
160}
161
162/// Required methods for elastic-plastic solid constitutive models.
163pub trait ElasticPlastic
164where
165    Self: ElasticPlasticOrViscoplastic,
166{
167}