sparkl2d_kernels/
gpu_constitutive_model.rs

1use crate::DevicePointer;
2use sparkl_core::dynamics::{ParticleData, ParticleVolume};
3use sparkl_core::math::{Matrix, Real};
4use sparkl_core::prelude::{
5    ActiveTimestepBounds, CorotatedLinearElasticity, MonaghanSphEos, NeoHookeanElasticity,
6    ParticleVelocity,
7};
8
9#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
10#[derive(cust_core::DeviceCopy, Copy, Clone, PartialEq)]
11#[repr(C)]
12pub enum GpuConstitutiveModel {
13    CorotatedLinearElasticity(CorotatedLinearElasticity, DevicePointer<ParticleData>),
14    NeoHookeanElasticity(NeoHookeanElasticity, DevicePointer<ParticleData>),
15    EosMonaghanSph(MonaghanSphEos),
16    Custom(u32),
17}
18
19impl GpuConstitutiveModel {
20    pub fn is_fluid(&self) -> bool {
21        match self {
22            Self::CorotatedLinearElasticity(m, _) => m.is_fluid(),
23            Self::NeoHookeanElasticity(m, _) => m.is_fluid(),
24            Self::EosMonaghanSph(m) => m.is_fluid(),
25            Self::Custom(_) => false,
26        }
27    }
28    pub unsafe fn pos_energy(
29        &self,
30        particle_id: u32,
31        particle_volume: &ParticleVolume,
32        particle_phase: Real,
33    ) -> Real {
34        match self {
35            Self::CorotatedLinearElasticity(m, d) => {
36                let hardening = (*d.as_ptr().add(particle_id as usize)).elastic_hardening;
37                m.pos_energy(particle_volume.deformation_gradient, hardening)
38            }
39            Self::NeoHookeanElasticity(m, d) => {
40                let hardening = (*d.as_ptr().add(particle_id as usize)).elastic_hardening;
41                m.pos_energy(
42                    particle_phase,
43                    hardening,
44                    &particle_volume.deformation_gradient,
45                )
46            }
47            Self::EosMonaghanSph(..) => 0.0,
48            Self::Custom(_) => 0.0,
49        }
50    }
51
52    pub unsafe fn kirchhoff_stress(
53        &self,
54        particle_id: u32,
55        particle_volume: &ParticleVolume,
56        particle_phase: Real,
57        velocity_gradient: &Matrix<Real>,
58    ) -> Matrix<Real> {
59        match self {
60            Self::CorotatedLinearElasticity(m, d) => {
61                let hardening = (*d.as_ptr().add(particle_id as usize)).elastic_hardening;
62                m.kirchhoff_stress(
63                    particle_phase,
64                    hardening,
65                    &particle_volume.deformation_gradient,
66                )
67            }
68            Self::NeoHookeanElasticity(m, d) => {
69                let hardening = (*d.as_ptr().add(particle_id as usize)).elastic_hardening;
70                m.kirchhoff_stress(
71                    particle_phase,
72                    hardening,
73                    &particle_volume.deformation_gradient,
74                )
75            }
76            Self::EosMonaghanSph(m) => m.kirchhoff_stress(
77                particle_volume.mass,
78                particle_volume.volume0,
79                particle_volume.density_fluid(),
80                particle_volume.plastic_deformation_gradient_det,
81                &velocity_gradient,
82            ),
83            Self::Custom(_) => Matrix::zeros(),
84        }
85    }
86
87    pub unsafe fn update_internal_energy_and_pressure(
88        &self,
89        _particle_id: u32,
90        _particle_volume: &ParticleVolume,
91        _dt: Real,
92        _cell_width: Real,
93        _velocity_gradient: &Matrix<Real>,
94    ) {
95        match self {
96            Self::CorotatedLinearElasticity(..)
97            | Self::NeoHookeanElasticity(..)
98            | Self::EosMonaghanSph(..)
99            | Self::Custom(_) => {}
100        }
101    }
102
103    pub fn active_timestep_bounds(&self) -> ActiveTimestepBounds {
104        match self {
105            Self::CorotatedLinearElasticity(m, _) => m.active_timestep_bounds(),
106            Self::NeoHookeanElasticity(m, _) => m.active_timestep_bounds(),
107            Self::EosMonaghanSph(m) => m.active_timestep_bounds(),
108            Self::Custom(_) => ActiveTimestepBounds::NONE,
109        }
110    }
111
112    pub unsafe fn timestep_bound(
113        &self,
114        particle_id: u32,
115        particle_volume: &ParticleVolume,
116        particle_vel: &ParticleVelocity,
117        cell_width: Real,
118    ) -> Real {
119        match self {
120            Self::CorotatedLinearElasticity(m, d) => {
121                let hardening = (*d.as_ptr().add(particle_id as usize)).elastic_hardening;
122                m.timestep_bound(
123                    particle_volume.density0(),
124                    &particle_vel.vector,
125                    hardening,
126                    cell_width,
127                )
128            }
129            Self::NeoHookeanElasticity(m, d) => {
130                let hardening = (*d.as_ptr().add(particle_id as usize)).elastic_hardening;
131                m.timestep_bound(
132                    particle_volume.density0(),
133                    &particle_vel.vector,
134                    cell_width,
135                    hardening,
136                )
137            }
138            Self::EosMonaghanSph(m) => m.timestep_bound(
139                particle_volume.fluid_deformation_gradient_det(),
140                particle_volume.mass,
141                particle_volume.volume0,
142                particle_volume.density_fluid(),
143                &particle_vel.vector,
144                cell_width,
145            ),
146            Self::Custom(_) => 0.0,
147        }
148    }
149}