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}