1use crate::domain::VoxelPlainIndex;
2use crate::errors::{CalcError, RngError};
3use crate::interaction::*;
4use crate::mechanics::{Mechanics, Position, Velocity};
5
6use serde::{Deserialize, Serialize};
7
8#[cfg_attr(feature = "pyo3", pyo3::pyclass)]
17#[derive(Clone, Copy, Debug, Deserialize, Hash, PartialEq, Eq, Ord, PartialOrd, Serialize)]
18pub enum CellIdentifier {
19 Division(VoxelPlainIndex, u64),
21 Initial(usize),
23 Inserted(VoxelPlainIndex, u64),
25}
26
27#[cfg(feature = "pyo3")]
28#[pyo3::pymethods]
29impl CellIdentifier {
30 #[new]
32 pub fn new(voxel_plain_index: VoxelPlainIndex, counter: u64) -> Self {
33 CellIdentifier::Division(voxel_plain_index, counter)
34 }
35
36 #[staticmethod]
38 pub fn new_initial(index: usize) -> Self {
39 CellIdentifier::Initial(index)
40 }
41
42 #[staticmethod]
44 pub fn new_inserted(voxel_plain_index: VoxelPlainIndex, counter: u64) -> Self {
45 Self::Inserted(voxel_plain_index, counter)
46 }
47
48 pub fn __deepcopy__(&self, _memo: pyo3::Bound<pyo3::types::PyDict>) -> Self {
50 *self
51 }
52
53 pub fn copy(&self) -> Self {
55 *self
56 }
57
58 pub fn __copy__(&self) -> Self {
60 *self
61 }
62
63 pub fn __repr__(&self) -> String {
65 format!("{:?}", self)
66 }
67
68 pub fn __eq__(&self, other: &Self) -> bool {
70 self.eq(other)
71 }
72
73 pub fn __hash__(&self) -> u64 {
75 use core::hash::{Hash, Hasher};
76 let mut hasher = std::collections::hash_map::DefaultHasher::new();
77 self.hash(&mut hasher);
78 hasher.finish()
79 }
80
81 pub fn __lt__(&self, other: &Self) -> bool {
83 self.lt(other)
84 }
85
86 pub fn __getitem__<'py>(
89 &self,
90 py: pyo3::Python<'py>,
91 key: usize,
92 ) -> pyo3::PyResult<pyo3::Bound<'py, pyo3::PyAny>> {
93 use pyo3::IntoPyObject;
94 let (key0, key1) = match self {
95 CellIdentifier::Initial(key0) => (*key0, None),
96 CellIdentifier::Division(key0, key1) => (key0.0, Some(*key1)),
97 CellIdentifier::Inserted(key0, key1) => (key0.0, Some(*key1)),
98 };
99 if key == 0 {
100 Ok(key0.into_pyobject(py)?.into_any())
101 } else if key == 1 {
102 Ok(key1.into_pyobject(py)?.into_any())
103 } else {
104 Err(pyo3::exceptions::PyValueError::new_err(
105 "CellIdentifier can only be indexed at 0 and 1",
106 ))
107 }
108 }
109}
110
111pub trait Id {
113 type Identifier;
116
117 fn get_id(&self) -> Self::Identifier;
119 fn ref_id(&self) -> &Self::Identifier;
121}
122
123#[derive(Clone, Deserialize, Serialize)]
128pub struct CellBox<C> {
129 pub identifier: CellIdentifier,
133 pub parent: Option<CellIdentifier>,
135 pub cell: C,
137}
138
139impl<Cel> Id for CellBox<Cel> {
140 type Identifier = CellIdentifier;
141
142 fn get_id(&self) -> CellIdentifier {
143 self.identifier
144 }
145
146 fn ref_id(&self) -> &CellIdentifier {
147 &self.identifier
148 }
149}
150
151impl<Cel> CellBox<Cel> {
152 pub fn get_parent_id(&self) -> Option<CellIdentifier> {
154 self.parent
155 }
156}
157
158impl<Inf, A> InteractionInformation<Inf> for CellBox<A>
159where
160 A: InteractionInformation<Inf>,
161{
162 fn get_interaction_information(&self) -> Inf {
163 self.cell.get_interaction_information()
164 }
165}
166
167impl<Pos, Vel, For, Inf, A> Interaction<Pos, Vel, For, Inf> for CellBox<A>
169where
170 A: Interaction<Pos, Vel, For, Inf> + Serialize + for<'a> Deserialize<'a>,
171{
172 fn calculate_force_between(
173 &self,
174 own_pos: &Pos,
175 own_vel: &Vel,
176 ext_pos: &Pos,
177 ext_vel: &Vel,
178 ext_information: &Inf,
179 ) -> Result<(For, For), CalcError> {
180 self.cell
181 .calculate_force_between(own_pos, own_vel, ext_pos, ext_vel, ext_information)
182 }
183
184 fn is_neighbor(&self, own_pos: &Pos, ext_pos: &Pos, ext_inf: &Inf) -> Result<bool, CalcError> {
185 self.cell.is_neighbor(own_pos, ext_pos, ext_inf)
186 }
187
188 fn react_to_neighbors(&mut self, neighbors: usize) -> Result<(), CalcError> {
189 self.cell.react_to_neighbors(neighbors)
190 }
191}
192
193impl<A, Pos> Position<Pos> for CellBox<A>
194where
195 A: Position<Pos>,
196{
197 fn pos(&self) -> Pos {
198 self.cell.pos()
199 }
200
201 fn set_pos(&mut self, pos: &Pos) {
202 self.cell.set_pos(pos)
203 }
204}
205
206impl<A, Vel> Velocity<Vel> for CellBox<A>
207where
208 A: Velocity<Vel>,
209{
210 fn velocity(&self) -> Vel {
211 self.cell.velocity()
212 }
213
214 fn set_velocity(&mut self, velocity: &Vel) {
215 self.cell.set_velocity(velocity)
216 }
217}
218
219impl<Pos, Vel, For, Float, A> Mechanics<Pos, Vel, For, Float> for CellBox<A>
220where
221 A: Mechanics<Pos, Vel, For, Float>,
222{
223 fn get_random_contribution(
224 &self,
225 rng: &mut rand_chacha::ChaCha8Rng,
226 dt: Float,
227 ) -> Result<(Pos, Vel), RngError> {
228 self.cell.get_random_contribution(rng, dt)
229 }
230
231 fn calculate_increment(&self, force: For) -> Result<(Pos, Vel), CalcError> {
232 self.cell.calculate_increment(force)
233 }
234}
235
236impl<C> core::ops::Deref for CellBox<C> {
237 type Target = C;
238
239 fn deref(&self) -> &Self::Target {
240 &self.cell
241 }
242}
243
244impl<C> core::ops::DerefMut for CellBox<C> {
245 fn deref_mut(&mut self) -> &mut Self::Target {
246 &mut self.cell
247 }
248}
249
250impl<C> CellBox<C> {
251 pub fn new_initial(n_cell: usize, cell: C) -> CellBox<C> {
253 CellBox::<C> {
254 identifier: CellIdentifier::Initial(n_cell),
255 parent: None,
256 cell,
257 }
258 }
259
260 pub fn new(
263 voxel_index: VoxelPlainIndex,
264 n_cell: u64,
265 cell: C,
266 parent: Option<CellIdentifier>,
267 ) -> CellBox<C> {
268 CellBox::<C> {
269 identifier: CellIdentifier::Division(voxel_index, n_cell),
270 parent,
271 cell,
272 }
273 }
274}
275
276#[doc(inline)]
277pub use cellular_raza_concepts_derive::CellAgent;