sparkl2d/dynamics/
particle_model.rs1use crate::dynamics::models::{ConstitutiveModel, FailureModel, PlasticModel};
2use rapier::data::{Arena, Index};
3use std::sync::Arc;
4
5#[cfg(feature = "serde-serialize")]
6use {
7 crate::dynamics::models::{CoreConstitutiveModel, CoreFailureModel, CorePlasticModel},
8 serde::{Deserialize, Deserializer, Serialize, Serializer},
9};
10
11pub type ParticleModelHandle = Index;
12
13#[derive(Clone)]
14pub struct ParticleModel {
15 pub constitutive_model: Arc<dyn ConstitutiveModel>,
16 pub plastic_model: Option<Arc<dyn PlasticModel>>,
17 pub failure_model: Option<Arc<dyn FailureModel>>,
18}
19
20#[cfg(feature = "serde-serialize")]
21impl Serialize for ParticleModel {
22 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
23 where
24 S: Serializer,
25 {
26 let typed_data = (
27 self.constitutive_model.to_core_model(),
28 self.plastic_model.as_ref().map(|m| {
29 m.to_core_model()
30 .expect("Unsupported model for serialization.")
31 }),
32 self.failure_model.as_ref().map(|m| {
33 m.to_core_model()
34 .expect("Unsupported model for serialization.")
35 }),
36 );
37 typed_data.serialize(serializer)
38 }
39}
40
41#[cfg(feature = "serde-serialize")]
42impl<'de> Deserialize<'de> for ParticleModel {
43 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
44 where
45 D: Deserializer<'de>,
46 {
47 let typed_data: (
48 CoreConstitutiveModel,
49 Option<CorePlasticModel>,
50 Option<CoreFailureModel>,
51 ) = Deserialize::deserialize(deserializer)?;
52
53 let constitutive_model = match typed_data.0 {
54 CoreConstitutiveModel::EosMonaghanSph(m) => Arc::new(m) as Arc<dyn ConstitutiveModel>,
55 CoreConstitutiveModel::NeoHookeanElasticity(m) => {
56 Arc::new(m) as Arc<dyn ConstitutiveModel>
57 }
58 CoreConstitutiveModel::CorotatedLinearElasticity(m) => {
59 Arc::new(m) as Arc<dyn ConstitutiveModel>
60 }
61 CoreConstitutiveModel::Custom(_) => todo!(),
62 };
63 let plastic_model = typed_data.1.map(|data| match data {
64 CorePlasticModel::Snow(m) => Arc::new(m) as Arc<dyn PlasticModel>,
65 CorePlasticModel::Rankine(m) => Arc::new(m) as Arc<dyn PlasticModel>,
66 CorePlasticModel::Nacc(m) => Arc::new(m) as Arc<dyn PlasticModel>,
67 CorePlasticModel::DruckerPrager(m) => Arc::new(m) as Arc<dyn PlasticModel>,
68 CorePlasticModel::Custom(_) => todo!(),
69 });
70
71 let failure_model = typed_data.2.map(|data| match data {
72 CoreFailureModel::MaximumStress(m) => Arc::new(m) as Arc<dyn FailureModel>,
73 CoreFailureModel::Custom(_) => todo!(),
74 });
75
76 Ok(Self {
77 constitutive_model,
78 plastic_model,
79 failure_model,
80 })
81 }
82}
83
84impl ParticleModel {
85 pub fn new(constitutive_model: impl ConstitutiveModel + 'static) -> Self {
86 Self {
87 constitutive_model: Arc::new(constitutive_model),
88 plastic_model: None,
89 failure_model: None,
90 }
91 }
92
93 pub fn with_plasticity(
94 constitutive_model: impl ConstitutiveModel + 'static,
95 plasticity: impl PlasticModel + 'static,
96 ) -> Self {
97 Self {
98 constitutive_model: Arc::new(constitutive_model),
99 plastic_model: Some(Arc::new(plasticity)),
100 failure_model: None,
101 }
102 }
103
104 pub fn with_failure(
105 constitutive_model: impl ConstitutiveModel + 'static,
106 failure: impl FailureModel + 'static,
107 ) -> Self {
108 Self {
109 constitutive_model: Arc::new(constitutive_model),
110 plastic_model: None,
111 failure_model: Some(Arc::new(failure)),
112 }
113 }
114}
115
116#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
117pub struct ParticleModelSet {
118 models: Arena<ParticleModel>,
119}
120
121impl ParticleModelSet {
122 pub fn new() -> Self {
123 Self {
124 models: Arena::new(),
125 }
126 }
127
128 pub fn insert(&mut self, model: ParticleModel) -> ParticleModelHandle {
129 self.models.insert(model)
130 }
131
132 pub fn get(&self, handle: ParticleModelHandle) -> Option<&ParticleModel> {
133 self.models.get(handle)
134 }
135
136 pub fn iter(&self) -> impl Iterator<Item = (Index, &ParticleModel)> {
137 self.models.iter()
138 }
139}
140
141impl std::ops::Index<ParticleModelHandle> for ParticleModelSet {
142 type Output = ParticleModel;
143
144 #[inline]
145 fn index(&self, i: ParticleModelHandle) -> &ParticleModel {
146 &self.models[i]
147 }
148}
149
150impl std::ops::IndexMut<ParticleModelHandle> for ParticleModelSet {
151 #[inline]
152 fn index_mut(&mut self, i: ParticleModelHandle) -> &mut ParticleModel {
153 &mut self.models[i]
154 }
155}