sparkl2d_core/dynamics/models/
plasticity_snow.rs

1use crate::math::{Matrix, Real, Vector};
2
3#[cfg(not(feature = "std"))]
4use na::ComplexField;
5
6/// The Snow plasticity model.
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 SnowPlasticity {
12    pub min_epsilon: Real,
13    pub max_epsilon: Real,
14    pub hardening_coeff: Real, // Typically between 3 and 10
15}
16
17impl SnowPlasticity {
18    pub fn new() -> Self {
19        SnowPlasticity {
20            min_epsilon: 2.5e-2,
21            max_epsilon: 4.5e-3,
22            hardening_coeff: 10.0,
23        }
24    }
25
26    pub fn project_deformation_gradient(&self, singular_values: Vector<Real>) -> Vector<Real> {
27        singular_values.map(|e| e.max(1.0 - self.min_epsilon).min(1.0 + self.max_epsilon))
28    }
29
30    pub fn update_particle(
31        &self,
32        particle_deformation_gradient: &mut Matrix<Real>,
33        particle_elastic_hardening: &mut Real,
34        particle_plastic_deformation_gradient_det: &mut Real,
35    ) {
36        let mut svd = particle_deformation_gradient.svd_unordered(true, true);
37
38        let new_sig_vals = self.project_deformation_gradient(svd.singular_values);
39
40        *particle_plastic_deformation_gradient_det *=
41            svd.singular_values.product() / new_sig_vals.product();
42
43        *particle_elastic_hardening =
44            (self.hardening_coeff * (1.0 - *particle_plastic_deformation_gradient_det)).exp();
45
46        svd.singular_values = new_sig_vals;
47        *particle_deformation_gradient = svd.recompose().unwrap();
48    }
49}