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
185impl<A, Pos> Position<Pos> for CellBox<A>
186where
187 A: Position<Pos>,
188{
189 fn pos(&self) -> Pos {
190 self.cell.pos()
191 }
192
193 fn set_pos(&mut self, pos: &Pos) {
194 self.cell.set_pos(pos)
195 }
196}
197
198impl<A, Vel> Velocity<Vel> for CellBox<A>
199where
200 A: Velocity<Vel>,
201{
202 fn velocity(&self) -> Vel {
203 self.cell.velocity()
204 }
205
206 fn set_velocity(&mut self, velocity: &Vel) {
207 self.cell.set_velocity(velocity)
208 }
209}
210
211impl<Pos, Vel, For, Float, A> Mechanics<Pos, Vel, For, Float> for CellBox<A>
212where
213 A: Mechanics<Pos, Vel, For, Float>,
214{
215 fn get_random_contribution(
216 &self,
217 rng: &mut rand_chacha::ChaCha8Rng,
218 dt: Float,
219 ) -> Result<(Pos, Vel), RngError> {
220 self.cell.get_random_contribution(rng, dt)
221 }
222
223 fn calculate_increment(&self, force: For) -> Result<(Pos, Vel), CalcError> {
224 self.cell.calculate_increment(force)
225 }
226}
227
228impl<C> core::ops::Deref for CellBox<C> {
229 type Target = C;
230
231 fn deref(&self) -> &Self::Target {
232 &self.cell
233 }
234}
235
236impl<C> core::ops::DerefMut for CellBox<C> {
237 fn deref_mut(&mut self) -> &mut Self::Target {
238 &mut self.cell
239 }
240}
241
242impl<C> CellBox<C> {
243 pub fn new_initial(n_cell: usize, cell: C) -> CellBox<C> {
245 CellBox::<C> {
246 identifier: CellIdentifier::Initial(n_cell),
247 parent: None,
248 cell,
249 }
250 }
251
252 pub fn new(
255 voxel_index: VoxelPlainIndex,
256 n_cell: u64,
257 cell: C,
258 parent: Option<CellIdentifier>,
259 ) -> CellBox<C> {
260 CellBox::<C> {
261 identifier: CellIdentifier::Division(voxel_index, n_cell),
262 parent,
263 cell,
264 }
265 }
266}
267
268#[doc(inline)]
269pub use cellular_raza_concepts_derive::CellAgent;