sparkl2d/dynamics/
particle_model.rs

1use 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}