conspire/constitutive/fluid/viscoplastic/
mod.rs

1//! Viscoplastic fluid constitutive models.
2
3use crate::{
4    constitutive::{ConstitutiveError, fluid::plastic::Plastic},
5    math::{Rank2, Scalar, Tensor, TensorArray, TensorTuple, TensorTupleVec},
6    mechanics::{DeformationGradientPlastic, MandelStressElastic, StretchingRatePlastic},
7};
8
9/// Viscoplastic state variables.
10pub type ViscoplasticStateVariables<Y> = TensorTuple<DeformationGradientPlastic, Y>;
11
12/// Viscoplastic state variables history.
13pub type ViscoplasticStateVariablesHistory<Y> = TensorTupleVec<DeformationGradientPlastic, Y>;
14
15/// Required methods for viscoplastic fluid constitutive models.
16pub trait Viscoplastic<Y>
17where
18    Self: Plastic,
19    Y: Tensor,
20{
21    /// Returns the initial state of the variables.
22    fn initial_state(&self) -> ViscoplasticStateVariables<Y>;
23    /// Calculates and returns the plastic evolution.
24    ///
25    /// ```math
26    /// \dot{\mathbf{F}}_\mathrm{p} = \mathbf{D}_\mathrm{p}\cdot\mathbf{F}_\mathrm{p}\quad\text{and}\quad\dot{\varepsilon}_\mathrm{p} = |\mathbf{D}_\mathrm{p}|
27    /// ```
28    fn plastic_evolution(
29        &self,
30        mandel_stress: MandelStressElastic,
31        state_variables: &ViscoplasticStateVariables<Y>,
32    ) -> Result<ViscoplasticStateVariables<Y>, ConstitutiveError>;
33    /// Calculates and returns the rate of plastic stretching.
34    ///
35    /// ```math
36    /// \mathbf{D}_\mathrm{p} = d_0\left(\frac{|\mathbf{M}_\mathrm{e}'|}{Y(S)}\right)^{\footnotesize\tfrac{1}{m}}\frac{\mathbf{M}_\mathrm{e}'}{|\mathbf{M}_\mathrm{e}'|}
37    /// ```
38    fn plastic_stretching_rate(
39        &self,
40        deviatoric_mandel_stress: MandelStressElastic,
41        yield_stress: Scalar,
42    ) -> Result<StretchingRatePlastic, ConstitutiveError> {
43        let magnitude = deviatoric_mandel_stress.norm();
44        if magnitude == 0.0 {
45            Ok(StretchingRatePlastic::zero())
46        } else {
47            Ok(deviatoric_mandel_stress
48                * (self.reference_flow_rate() / magnitude
49                    * (magnitude / yield_stress).powf(1.0 / self.rate_sensitivity())))
50        }
51    }
52    /// Returns the rate_sensitivity parameter.
53    fn rate_sensitivity(&self) -> Scalar;
54    /// Returns the reference flow rate.
55    fn reference_flow_rate(&self) -> Scalar;
56}
57
58/// The viscoplastic flow model.
59#[derive(Clone, Debug)]
60pub struct ViscoplasticFlow {
61    /// The initial yield stress $`Y_0`$.
62    pub yield_stress: Scalar,
63    /// The isotropic hardening slope $`H`$.
64    pub hardening_slope: Scalar,
65    /// The rate sensitivity parameter $`m`$.
66    pub rate_sensitivity: Scalar,
67    /// The reference flow rate $`d_0`$.
68    pub reference_flow_rate: Scalar,
69}
70
71impl Plastic for ViscoplasticFlow {
72    fn initial_yield_stress(&self) -> Scalar {
73        self.yield_stress
74    }
75    fn hardening_slope(&self) -> Scalar {
76        self.hardening_slope
77    }
78}
79
80impl Viscoplastic<Scalar> for ViscoplasticFlow {
81    fn initial_state(&self) -> ViscoplasticStateVariables<Scalar> {
82        (DeformationGradientPlastic::identity(), 0.0).into()
83    }
84    fn plastic_evolution(
85        &self,
86        mandel_stress: MandelStressElastic,
87        state_variables: &ViscoplasticStateVariables<Scalar>,
88    ) -> Result<ViscoplasticStateVariables<Scalar>, ConstitutiveError> {
89        default_plastic_evolution(self, mandel_stress, state_variables)
90    }
91    fn rate_sensitivity(&self) -> Scalar {
92        self.rate_sensitivity
93    }
94    fn reference_flow_rate(&self) -> Scalar {
95        self.reference_flow_rate
96    }
97}
98
99pub fn default_plastic_evolution<C>(
100    model: &C,
101    mandel_stress: MandelStressElastic,
102    state_variables: &ViscoplasticStateVariables<Scalar>,
103) -> Result<ViscoplasticStateVariables<Scalar>, ConstitutiveError>
104where
105    C: Viscoplastic<Scalar>,
106{
107    let (deformation_gradient_p, &equivalent_plastic_strain) = state_variables.into();
108    let plastic_stretching_rate = model.plastic_stretching_rate(
109        mandel_stress.deviatoric(),
110        model.yield_stress(equivalent_plastic_strain)?,
111    )?;
112    let equivalent_plastic_strain_rate = plastic_stretching_rate.norm();
113    Ok((
114        plastic_stretching_rate * deformation_gradient_p,
115        equivalent_plastic_strain_rate,
116    )
117        .into())
118}