1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
use crate::math::{Matrix, Real, Vector};
#[cfg(not(feature = "std"))]
use na::ComplexField;
#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, Debug, PartialEq)]
#[repr(C)]
pub struct SnowPlasticity {
pub min_epsilon: Real,
pub max_epsilon: Real,
pub hardening_coeff: Real, }
impl SnowPlasticity {
pub fn new() -> Self {
SnowPlasticity {
min_epsilon: 2.5e-2,
max_epsilon: 4.5e-3,
hardening_coeff: 10.0,
}
}
pub fn project_deformation_gradient(&self, singular_values: Vector<Real>) -> Vector<Real> {
singular_values.map(|e| e.max(1.0 - self.min_epsilon).min(1.0 + self.max_epsilon))
}
pub fn update_particle(
&self,
particle_deformation_gradient: &mut Matrix<Real>,
particle_elastic_hardening: &mut Real,
particle_plastic_deformation_gradient_det: &mut Real,
) {
let mut svd = particle_deformation_gradient.svd_unordered(true, true);
let new_sig_vals = self.project_deformation_gradient(svd.singular_values);
*particle_plastic_deformation_gradient_det *=
svd.singular_values.product() / new_sig_vals.product();
*particle_elastic_hardening =
(self.hardening_coeff * (1.0 - *particle_plastic_deformation_gradient_det)).exp();
svd.singular_values = new_sig_vals;
*particle_deformation_gradient = svd.recompose().unwrap();
}
}