sparkl2d_core/dynamics/models/
plasticity_rankine.rs1use crate::math::{Matrix, Real, DIM};
2use core::cmp::Ordering;
3
4#[cfg(not(feature = "std"))]
5use na::ComplexField;
6
7#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
8#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
9#[derive(Copy, Clone, Debug, PartialEq)]
10#[repr(C)]
11pub struct RankinePlasticity {
12 mu: Real,
13 lambda: Real,
14 tensile_strength: Real,
15 softening_rate: Real,
16}
17
18impl RankinePlasticity {
19 pub fn new(
20 young_modulus: Real,
21 poisson_ratio: Real,
22 tensile_strength: Real,
23 softening_rate: Real,
24 ) -> Self {
25 let (lambda, mu) = crate::utils::lame_lambda_mu(young_modulus, poisson_ratio);
26
27 Self {
28 lambda,
29 mu,
30 tensile_strength,
31 softening_rate,
32 }
33 }
34
35 pub fn update_particle(
36 &self,
37 particle_deformation_gradient: &mut Matrix<Real>,
38 particle_plastic_hardening: &mut Real,
39 ) {
40 let lambda = self.lambda;
41 let mu = self.mu;
42
43 let mut svd = particle_deformation_gradient.svd_unordered(true, true);
44 let mut eigv = svd.singular_values.map(|s| s.ln()); let prev_eigv = eigv;
47 let mut idx = [0usize, 1, DIM - 1]; idx.sort_unstable_by(|a, b| eigv[*a].partial_cmp(&eigv[*b]).unwrap_or(Ordering::Equal));
49 let [e3, e2, e1] = idx;
50 let soft_tensile_strength = self.tensile_strength - (*particle_plastic_hardening - 1.0);
54
55 if lambda * eigv.sum() + 2.0 * mu * eigv[e1] <= soft_tensile_strength {
56 return;
58 } else if (2.0 * mu + lambda) * eigv[e2] + lambda * (eigv.sum() - eigv[e1])
59 <= soft_tensile_strength
60 {
61 let new_eigv =
62 (soft_tensile_strength - lambda * (eigv.sum() - eigv[e1])) / (2.0 * mu + lambda);
63 eigv[e1] = new_eigv;
64 } else if DIM == 3 && (2.0 * mu + 3.0 * lambda) * eigv[e3] <= soft_tensile_strength {
65 let new_eigv = (soft_tensile_strength - lambda * (eigv.sum() - eigv[e1] - eigv[e2]))
66 / (2.0 * mu + 2.0 * lambda);
67 eigv[e1] = new_eigv;
68 eigv[e2] = new_eigv;
69 } else {
70 let new_eigv = soft_tensile_strength / (2.0 * self.mu + 3.0 * self.lambda);
71 eigv.fill(new_eigv);
72 }
73
74 *particle_plastic_hardening += self.softening_rate * (prev_eigv - eigv).norm();
75 *particle_plastic_hardening = particle_plastic_hardening.min(self.tensile_strength);
76 svd.singular_values = eigv.map(|e| e.exp());
77 *particle_deformation_gradient = svd.recompose().unwrap();
78 }
79}