cellular_raza_core/backend/chili/
aux_storage.rs

1use cellular_raza_concepts::CycleEvent;
2pub use circ_buffer::*;
3use serde::{Deserialize, Serialize};
4
5pub use cellular_raza_concepts::Xapy;
6
7// --------------------------------- UPDATE-MECHANICS --------------------------------
8/// Used to store intermediate information about last positions and velocities.
9/// Can store up to `N` values.
10pub trait UpdateMechanics<Pos, Vel, For, const N: usize> {
11    /// Stores the last position of the cell. May overwrite old results depending on
12    /// how many old results are being stored.
13    fn set_last_position(&mut self, pos: Pos);
14
15    /// Get all previous positions. This number maybe smaller than the maximum number of stored
16    /// positions but never exceeds it.
17    fn previous_positions<'a>(&'a self) -> RingBufferIterRef<'a, Pos, N>;
18
19    /// Stores the last velocity of the cell. Overwrites old results when stored amount
20    /// exceeds number of maximum stored values.
21    fn set_last_velocity(&mut self, vel: Vel);
22
23    /// Get all previous velocities. This number may be smaller than the maximum number of stored
24    /// velocities but never exceeds it.
25    fn previous_velocities<'a>(&'a self) -> RingBufferIterRef<'a, Vel, N>;
26
27    /// Get the number of previous values currently stored
28    ///
29    /// This number is by definition between 0 and `N`.
30    fn n_previous_values(&self) -> usize;
31
32    /// Add force to currently stored forces
33    fn add_force(&mut self, force: For);
34
35    /// Obtain current force on cell
36    fn get_current_force_and_reset(&mut self) -> For;
37}
38
39/// Stores intermediate information about the mechanics of a cell.
40#[derive(Clone, Deserialize, Serialize)]
41pub struct AuxStorageMechanics<Pos, Vel, For, const N: usize> {
42    positions: RingBuffer<Pos, N>,
43    velocities: RingBuffer<Vel, N>,
44    current_force: For,
45    zero_force: For,
46}
47
48// It is necessary to implement this trait by hand since with the current version of the Mechanics
49// concept, we need to specify next_random_mechanics_update: Some(0.0) in order for any updates to
50// be done at all.
51impl<Pos, Vel, For, const N: usize> Default for AuxStorageMechanics<Pos, Vel, For, N>
52where
53    For: num::Zero,
54{
55    fn default() -> Self {
56        Self {
57            positions: RingBuffer::<Pos, N>::default(),
58            velocities: RingBuffer::<Vel, N>::default(),
59            current_force: num::Zero::zero(),
60            zero_force: num::Zero::zero(),
61        }
62    }
63}
64
65/// Used to construct initial (empty) AuxStorage variants.
66pub trait DefaultFrom<T> {
67    /// Constructs the Type in question from a given value. This is typically a zero value.
68    /// If it can be constructed from the [num::Zero] trait, this method is not required and
69    /// `cellular_raza` will determine the initial zero-value correctly.
70    /// For other types (ie. dynamically-sized ones) additional entries may be necessary.
71    fn default_from(value: &T) -> Self;
72}
73
74impl<Pos, Vel, For, const N: usize> DefaultFrom<For> for AuxStorageMechanics<Pos, Vel, For, N>
75where
76    For: Clone,
77{
78    fn default_from(value: &For) -> Self {
79        let force: For = value.clone().into();
80        Self {
81            positions: RingBuffer::default(),
82            velocities: RingBuffer::default(),
83            current_force: force.clone(),
84            zero_force: force.clone(),
85        }
86    }
87}
88
89impl<Pos, Vel, For, const N: usize> UpdateMechanics<Pos, Vel, For, N>
90    for AuxStorageMechanics<Pos, Vel, For, N>
91where
92    For: Clone + core::ops::AddAssign<For>,
93{
94    #[inline]
95    fn previous_positions<'a>(&'a self) -> RingBufferIterRef<'a, Pos, N> {
96        self.positions.iter()
97    }
98
99    #[inline]
100    fn previous_velocities<'a>(&'a self) -> RingBufferIterRef<'a, Vel, N> {
101        self.velocities.iter()
102    }
103
104    #[inline]
105    fn n_previous_values(&self) -> usize {
106        self.positions.get_size()
107    }
108
109    #[inline]
110    fn set_last_position(&mut self, pos: Pos) {
111        self.positions.push(pos);
112    }
113
114    #[inline]
115    fn set_last_velocity(&mut self, vel: Vel) {
116        self.velocities.push(vel);
117    }
118
119    #[inline]
120    fn add_force(&mut self, force: For) {
121        self.current_force += force;
122    }
123
124    #[inline]
125    fn get_current_force_and_reset(&mut self) -> For {
126        let f = self.current_force.clone();
127        self.current_force = self.zero_force.clone();
128        f
129    }
130}
131
132// ----------------------------------- UPDATE-CYCLE ----------------------------------
133/// Trait which describes how to store intermediate
134/// information on the cell cycle.
135pub trait UpdateCycle {
136    /// Set all cycle events. This function is currently the
137    /// only way to change the contents of the stored events.
138    fn set_cycle_events(&mut self, events: Vec<CycleEvent>);
139
140    /// Get all cycle events currently stored.
141    fn get_cycle_events(&self) -> &Vec<CycleEvent>;
142
143    /// Drain all cycle events
144    fn drain_cycle_events<'a>(&'a mut self) -> std::vec::Drain<'a, CycleEvent>;
145
146    /// Add another cycle event to the storage.
147    fn add_cycle_event(&mut self, event: CycleEvent);
148}
149
150/// Stores intermediate information about the cell cycle.
151///
152/// This struct is used in the [build_aux_storage](crate::backend::chili::build_aux_storage) macro.
153/// It can in principle also be re-used on its own since it implements the [UpdateCycle] trait.
154///
155/// ```
156/// use cellular_raza_core::backend::chili::{AuxStorageCycle,UpdateCycle};
157/// use cellular_raza_concepts::CycleEvent;
158///
159/// // Construct a new empty AuxStorageCycle
160/// let mut aux_storage_cycle = AuxStorageCycle::default();
161///
162/// // Add one element
163/// aux_storage_cycle.add_cycle_event(CycleEvent::Division);
164/// assert_eq!(aux_storage_cycle.get_cycle_events().len(), 1);
165///
166/// // Drain all elements currently present
167/// let events = aux_storage_cycle.drain_cycle_events();
168/// assert_eq!(events.len(), 1);
169/// ```
170#[derive(Clone, Default, Deserialize, Serialize)]
171pub struct AuxStorageCycle {
172    cycle_events: Vec<CycleEvent>,
173}
174
175impl UpdateCycle for AuxStorageCycle {
176    #[inline]
177    fn set_cycle_events(&mut self, events: Vec<CycleEvent>) {
178        self.cycle_events = events;
179    }
180
181    #[inline]
182    fn get_cycle_events(&self) -> &Vec<CycleEvent> {
183        &self.cycle_events
184    }
185
186    #[inline]
187    fn drain_cycle_events<'a>(&'a mut self) -> std::vec::Drain<'a, CycleEvent> {
188        self.cycle_events.drain(..)
189    }
190
191    #[inline]
192    fn add_cycle_event(&mut self, event: CycleEvent) {
193        self.cycle_events.push(event);
194    }
195}
196
197// --------------------------------- UPDATE-REACTIONS --------------------------------
198/// Interface to store intermediate information about cellular reactions.
199pub trait UpdateReactions<Ri> {
200    /// Set the value of intracellular concentrations
201    fn set_conc(&mut self, conc: Ri);
202    /// Obtain the current value of intracellular concentrations
203    fn get_conc(&self) -> Ri;
204    /// Add concentrations to the current value
205    fn incr_conc(&mut self, incr: Ri);
206}
207
208/// Helper storage for values regarding intracellular concentrations for the
209/// [Reactions](cellular_raza_concepts::Reactions) trait.
210#[derive(Clone, Default, Deserialize, Serialize)]
211pub struct AuxStorageReactions<Ri> {
212    concentration: Ri,
213}
214
215impl<Ri> DefaultFrom<Ri> for AuxStorageReactions<Ri>
216where
217    Ri: Clone,
218{
219    fn default_from(value: &Ri) -> Self {
220        AuxStorageReactions {
221            concentration: value.clone(),
222        }
223    }
224}
225
226impl<R> UpdateReactions<R> for AuxStorageReactions<R>
227where
228    R: Clone + core::ops::Add<R, Output = R>,
229{
230    #[inline]
231    fn get_conc(&self) -> R {
232        self.concentration.clone()
233    }
234
235    #[inline]
236    fn incr_conc(&mut self, incr: R) {
237        self.concentration = self.concentration.clone() + incr;
238    }
239
240    #[inline]
241    fn set_conc(&mut self, conc: R) {
242        self.concentration = conc;
243    }
244}
245
246/// Used to update properties of the cell related to the
247/// [ReactionsContact](cellular_raza_concepts::ReactionsContact) trait.
248pub trait UpdateReactionsContact<Ri, const N: usize> {
249    /// Sets the current contact reactions increment
250    fn set_current_increment(&mut self, new_increment: Ri);
251    /// Adds to the current increment
252    fn incr_current_increment(&mut self, increment: Ri);
253    /// Obtains the current increment
254    fn get_current_increment(&self) -> Ri;
255    /// Obtain previous increments used for adams_bashforth integrators
256    fn previous_increments<'a>(&'a self) -> RingBufferIterRef<'a, Ri, N>;
257    /// Set the last increment in the ring buffer
258    fn set_last_increment(&mut self, increment: Ri);
259    /// Get the number of previous values to match against [circ_buffer::RingBufferIterRef]
260    fn n_previous_values(&self) -> usize;
261}
262
263/// Implementor of the [UpdateReactionsContact] trait.
264#[derive(Clone, Default, Deserialize, Serialize)]
265pub struct AuxStorageReactionsContact<Ri, const N: usize> {
266    current_increment: Ri,
267    increments: RingBuffer<Ri, N>,
268}
269
270impl<Ri, const N: usize> DefaultFrom<Ri> for AuxStorageReactionsContact<Ri, N>
271where
272    Ri: Clone,
273{
274    fn default_from(value: &Ri) -> Self {
275        AuxStorageReactionsContact {
276            current_increment: value.clone(),
277            increments: Default::default(),
278        }
279    }
280}
281
282impl<Ri, const N: usize> UpdateReactionsContact<Ri, N> for AuxStorageReactionsContact<Ri, N>
283where
284    Ri: Clone + core::ops::Add<Ri, Output = Ri>,
285{
286    #[inline]
287    fn get_current_increment(&self) -> Ri {
288        self.current_increment.clone()
289    }
290
291    #[inline]
292    fn incr_current_increment(&mut self, increment: Ri) {
293        self.current_increment = self.current_increment.clone() + increment;
294    }
295
296    #[inline]
297    fn set_current_increment(&mut self, new_increment: Ri) {
298        self.current_increment = new_increment;
299    }
300
301    #[inline]
302    fn previous_increments<'a>(&'a self) -> RingBufferIterRef<'a, Ri, N> {
303        self.increments.iter()
304    }
305
306    #[inline]
307    fn set_last_increment(&mut self, increment: Ri) {
308        self.increments.push(increment)
309    }
310
311    #[inline]
312    fn n_previous_values(&self) -> usize {
313        self.increments.get_size()
314    }
315}
316
317// -------------------------------- UPDATE-Neighbor-Sensing -------------------------------
318/// Interface to store intermediate information about neighbors.
319pub trait UpdateNeighborSensing<Acc> {
320    /// Obtains the internally held accumulator for the [cellular_raza_concepts::NeighborSensing]
321    /// trait
322    fn get_accumulator(&mut self) -> &mut Acc;
323}
324
325/// Helper storage to update information about neighbors
326#[derive(Clone, Default, Deserialize, Serialize)]
327pub struct AuxStorageNeighborSensing<Acc> {
328    accumulator: Acc,
329}
330
331impl<Acc> UpdateNeighborSensing<Acc> for AuxStorageNeighborSensing<Acc> {
332    fn get_accumulator(&mut self) -> &mut Acc {
333        &mut self.accumulator
334    }
335}
336
337#[allow(unused)]
338#[doc(hidden)]
339mod test_derive_aux_storage_compile {
340    /// ```
341    /// use cellular_raza_core::backend::chili::AuxStorage;
342    /// use cellular_raza_core::backend::chili::*;
343    ///
344    /// #[derive(AuxStorage)]
345    /// struct TestStructMechanics<Pos, Vel, For, const N: usize> {
346    ///     #[UpdateMechanics(Pos, Vel, For, N)]
347    ///     aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
348    /// }
349    /// ```
350    fn mechanics_default() {}
351
352    /// ```
353    /// use cellular_raza_core::backend::chili::AuxStorage;
354    /// use cellular_raza_core::backend::chili::*;
355    ///
356    /// #[derive(AuxStorage)]
357    /// pub struct TestStructMechanics<Pos, Vel, For, const N: usize> {
358    ///     #[UpdateMechanics(Pos, Vel, For, N)]
359    ///     aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
360    /// }
361    /// ```
362    fn mechanics_visibility_1() {}
363
364    /// ```
365    /// use cellular_raza_core::backend::chili::AuxStorage;
366    /// use cellular_raza_core::backend::chili::*;
367    ///
368    /// #[derive(AuxStorage)]
369    /// pub(crate) struct TestStructMechanics<Pos, Vel, For, const N: usize> {
370    ///     #[UpdateMechanics(Pos, Vel, For, N)]
371    ///     aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
372    /// }
373    /// ```
374    fn mechanics_visibility_2() {}
375
376    /// ```
377    /// mod some_module {
378    ///     use cellular_raza_core::backend::chili::AuxStorage;
379    ///     use cellular_raza_core::backend::chili::*;
380    ///
381    ///     #[derive(AuxStorage)]
382    ///     pub(super) struct TestStructMechanics<Pos, Vel, For, const N: usize> {
383    ///         #[UpdateMechanics(Pos, Vel, For, N)]
384    ///         aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
385    ///     }
386    /// }
387    /// fn use_impl<T, Pos, Vel, For, const N: usize>(
388    ///     mut aux_storage: T
389    /// ) -> For
390    /// where
391    ///     T: cellular_raza_core::backend::chili::UpdateMechanics<Pos, Vel, For, N>,
392    /// {
393    ///     aux_storage.get_current_force_and_reset()
394    /// }
395    /// ```
396    fn mechanics_visibility_3() {}
397
398    /// ```
399    /// use cellular_raza_core::backend::chili::AuxStorage;
400    /// use cellular_raza_core::backend::chili::*;
401    ///
402    /// #[derive(AuxStorage)]
403    /// struct TestStructMechanics<Pos, Vel, For, T, const N: usize> {
404    ///     #[UpdateMechanics(Pos, Vel, For, N)]
405    ///     aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
406    ///     other: T,
407    /// }
408    /// ```
409    fn mechanics_more_struct_generics() {}
410
411    /// ```
412    /// use cellular_raza_core::backend::chili::AuxStorage;
413    /// use cellular_raza_core::backend::chili::*;
414    ///
415    /// #[derive(AuxStorage)]
416    /// struct TestStructMechanics<Pos, Vel, For, const N: usize, const M: usize> {
417    ///     #[UpdateMechanics(Pos, Vel, For, N)]
418    ///     aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
419    ///     count: [i64; M],
420    /// }
421    /// ```
422    fn mechanics_more_struct_const_generics() {}
423
424    /// ```
425    /// use cellular_raza_core::backend::chili::AuxStorage;
426    /// use cellular_raza_core::backend::chili::*;
427    ///
428    /// #[derive(AuxStorage)]
429    /// struct TestStructMechanics<Pos, Vel, For, const N: usize>
430    /// where
431    ///     Pos: Clone,
432    /// {
433    ///     #[UpdateMechanics(Pos, Vel, For, N)]
434    ///     aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
435    /// }
436    /// ```
437    fn mechanics_where_clause() {}
438
439    /// ```
440    /// use cellular_raza_core::backend::chili::AuxStorage;
441    /// use cellular_raza_core::backend::chili::*;
442    ///
443    /// #[derive(AuxStorage)]
444    /// struct TestStructMechanics<Pos, Vel, For, const N: usize> {
445    ///     #[UpdateMechanics(Pos, Vel, For, N)]
446    ///     #[cfg(not(test))]
447    ///     aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
448    /// }
449    /// ```
450    fn mechanics_other_attributes() {}
451
452    /// ```
453    /// use cellular_raza_core::backend::chili::AuxStorage;
454    /// use cellular_raza_core::backend::chili::*;
455    /// use cellular_raza_concepts::CycleEvent;
456    ///
457    /// #[derive(AuxStorage)]
458    /// struct TestStructCycle {
459    ///     #[UpdateCycle]
460    ///     aux_cycle: AuxStorageCycle,
461    /// }
462    /// ```
463    fn cycle_default() {}
464
465    /// ```
466    /// use cellular_raza_core::backend::chili::AuxStorage;
467    /// use cellular_raza_core::backend::chili::*;
468    /// use cellular_raza_concepts::CycleEvent;
469    ///
470    /// #[derive(AuxStorage)]
471    /// pub struct TestStructCycle {
472    ///     #[UpdateCycle]
473    ///     aux_cycle: AuxStorageCycle,
474    /// }
475    /// ```
476    fn cycle_visibility_1() {}
477
478    /// ```
479    /// use cellular_raza_core::backend::chili::AuxStorage;
480    /// use cellular_raza_core::backend::chili::*;
481    /// use cellular_raza_concepts::CycleEvent;
482    ///
483    /// #[derive(AuxStorage)]
484    /// pub(crate) struct TestStructCycle {
485    ///     #[UpdateCycle]
486    ///     aux_cycle: AuxStorageCycle,
487    /// }
488    /// ```
489    fn cycle_visibility_2() {}
490
491    /// ```
492    /// use cellular_raza_core::backend::chili::AuxStorage;
493    /// use cellular_raza_core::backend::chili::*;
494    /// use cellular_raza_concepts::CycleEvent;
495    ///
496    /// #[derive(AuxStorage)]
497    /// pub struct TestStructCycle<T> {
498    ///     #[UpdateCycle]
499    ///     aux_cycle: AuxStorageCycle,
500    ///     _generic: T,
501    /// }
502    /// ```
503    fn cycle_generic_param() {}
504
505    /// ```
506    /// use cellular_raza_core::backend::chili::AuxStorage;
507    /// use cellular_raza_core::backend::chili::*;
508    /// use cellular_raza_concepts::CycleEvent;
509    ///
510    /// #[derive(AuxStorage)]
511    /// pub struct TestStructCycle<const N: usize> {
512    ///     #[UpdateCycle]
513    ///     aux_cycle: AuxStorageCycle,
514    ///     _generic: [f64; N],
515    /// }
516    /// ```
517    fn cycle_const_generic_param() {}
518
519    /// ```
520    /// use cellular_raza_core::backend::chili::AuxStorage;
521    /// use cellular_raza_core::backend::chili::*;
522    /// use cellular_raza_concepts::CycleEvent;
523    ///
524    /// #[derive(AuxStorage)]
525    /// pub struct TestStructCycle<T>
526    /// where
527    ///     T: Clone,
528    /// {
529    ///     #[UpdateCycle]
530    ///     aux_cycle: AuxStorageCycle,
531    ///     _generic: T,
532    /// }
533    /// ```
534    fn cycle_where_clause() {}
535
536    /// ```
537    /// use cellular_raza_core::backend::chili::AuxStorage;
538    /// use cellular_raza_core::backend::chili::*;
539    /// use cellular_raza_concepts::CycleEvent;
540    ///
541    /// #[derive(AuxStorage)]
542    /// struct TestStructCycle {
543    ///     #[UpdateCycle]
544    ///     #[cfg(not(test))]
545    ///     aux_cycle: AuxStorageCycle,
546    /// }
547    /// ```
548    fn cycle_other_attributes() {}
549
550    /// ```
551    /// use cellular_raza_core::backend::chili::AuxStorage;
552    /// use cellular_raza_core::backend::chili::*;
553    ///
554    /// #[derive(AuxStorage)]
555    /// struct TestStructReactions<R> {
556    ///     #[UpdateReactions(R)]
557    ///     aux_cycle: AuxStorageReactions<R>,
558    /// }
559    /// ```
560    fn reactions_default() {}
561
562    /// ```
563    /// use cellular_raza_core::backend::chili::AuxStorage;
564    /// use cellular_raza_core::backend::chili::*;
565    ///
566    /// #[derive(AuxStorage)]
567    /// pub struct TestStructReactions<R> {
568    ///     #[UpdateReactions(R)]
569    ///     aux_cycle: AuxStorageReactions<R>,
570    /// }
571    /// ```
572    fn reactions_visibility_1() {}
573
574    /// ```
575    /// use cellular_raza_core::backend::chili::AuxStorage;
576    /// use cellular_raza_core::backend::chili::*;
577    ///
578    /// #[derive(AuxStorage)]
579    /// pub(crate) struct TestStructReactions<R> {
580    ///     #[UpdateReactions(R)]
581    ///     aux_cycle: AuxStorageReactions<R>,
582    /// }
583    /// ```
584    fn reactions_visibility_2() {}
585
586    /// ```
587    /// use cellular_raza_core::backend::chili::AuxStorage;
588    /// use cellular_raza_core::backend::chili::*;
589    ///
590    /// #[derive(AuxStorage)]
591    /// struct TestStructReactions<T, R> {
592    ///     #[UpdateReactions(R)]
593    ///     aux_cycle: AuxStorageReactions<R>,
594    ///     generic: T,
595    /// }
596    /// ```
597    fn reactions_generic_param() {}
598
599    /// ```
600    /// use cellular_raza_core::backend::chili::AuxStorage;
601    /// use cellular_raza_core::backend::chili::*;
602    ///
603    /// #[derive(AuxStorage)]
604    /// struct TestStructReactions<R, const N: usize> {
605    ///     #[UpdateReactions(R)]
606    ///     aux_cycle: AuxStorageReactions<R>,
607    ///     generic_array: [usize; N],
608    /// }
609    /// ```
610    fn reactions_const_generic_param() {}
611
612    /// ```
613    /// use cellular_raza_core::backend::chili::AuxStorage;
614    /// use cellular_raza_core::backend::chili::*;
615    ///
616    /// #[derive(AuxStorage)]
617    /// struct TestStructReactions<T, R>
618    /// where
619    ///     T: Clone,
620    /// {
621    ///     #[UpdateReactions(R)]
622    ///     aux_cycle: AuxStorageReactions<R>,
623    ///     generic: T,
624    /// }
625    /// ```
626    fn reactions_where_clause() {}
627
628    /// ```
629    /// use cellular_raza_core::backend::chili::AuxStorage;
630    /// use cellular_raza_core::backend::chili::*;
631    ///
632    /// #[derive(AuxStorage)]
633    /// struct TestStructReactions<R> {
634    ///     #[cfg(not(test))]
635    ///     #[UpdateReactions(R)]
636    ///     aux_cycle: AuxStorageReactions<R>,
637    /// }
638    /// ```
639    fn reactions_other_attributes() {}
640
641    /// ```
642    /// use cellular_raza_core::backend::chili::AuxStorage;
643    /// use cellular_raza_core::backend::chili::*;
644    ///
645    /// #[derive(AuxStorage)]
646    /// struct TestStructInteraction<A> {
647    ///     #[UpdateNeighborSensing(A)]
648    ///     aux_interaction: AuxStorageNeighborSensing<A>,
649    /// }
650    /// ```
651    fn neighbor_sensing_default() {}
652
653    /// ```
654    /// use cellular_raza_core::backend::chili::AuxStorage;
655    /// use cellular_raza_core::backend::chili::*;
656    ///
657    /// #[derive(AuxStorage)]
658    /// pub struct TestStructInteraction<A> {
659    ///     #[UpdateNeighborSensing(A)]
660    ///     aux_interaction: AuxStorageNeighborSensing<A>,
661    /// }
662    /// ```
663    fn neighbor_sensing_visibility_1() {}
664
665    /// ```
666    /// use cellular_raza_core::backend::chili::AuxStorage;
667    /// use cellular_raza_core::backend::chili::*;
668    ///
669    /// #[derive(AuxStorage)]
670    /// pub(crate) struct TestStructInteraction<A> {
671    ///     #[UpdateNeighborSensing(A)]
672    ///     aux_interaction: AuxStorageNeighborSensing<A>,
673    /// }
674    /// ```
675    fn neighbor_sensing_visibility_2() {}
676
677    /// ```
678    /// use cellular_raza_core::backend::chili::AuxStorage;
679    /// use cellular_raza_core::backend::chili::*;
680    ///
681    /// #[derive(AuxStorage)]
682    /// struct TestStructInteraction<A, T> {
683    ///     #[UpdateNeighborSensing(A)]
684    ///     aux_interaction: AuxStorageNeighborSensing<A>,
685    ///     generic: T,
686    /// }
687    /// ```
688    fn neighbor_sensing_generic_param() {}
689
690    /// ```
691    /// use cellular_raza_core::backend::chili::AuxStorage;
692    /// use cellular_raza_core::backend::chili::*;
693    ///
694    /// #[derive(AuxStorage)]
695    /// struct TestStructInteraction<A, const N: usize> {
696    ///     #[UpdateNeighborSensing(A)]
697    ///     aux_interaction: AuxStorageNeighborSensing<A>,
698    ///     generic: [f64; N],
699    /// }
700    /// ```
701    fn neighbor_sensing_const_generic_param() {}
702
703    /// ```
704    /// use cellular_raza_core::backend::chili::AuxStorage;
705    /// use cellular_raza_core::backend::chili::*;
706    ///
707    /// #[derive(AuxStorage)]
708    /// struct TestStructInteraction<A, T>
709    /// where
710    ///     T: Clone,
711    /// {
712    ///     #[UpdateNeighborSensing(A)]
713    ///     aux_interaction: AuxStorageNeighborSensing<A>,
714    ///     generic: T,
715    /// }
716    /// ```
717    fn neighbor_sensing_where_clause() {}
718
719    /// ```
720    /// use cellular_raza_core::backend::chili::AuxStorage;
721    /// use cellular_raza_core::backend::chili::*;
722    ///
723    /// #[derive(AuxStorage)]
724    /// struct TestStructInteraction<A> {
725    ///     #[UpdateNeighborSensing(A)]
726    ///     #[cfg(not(test))]
727    ///     aux_interaction: AuxStorageNeighborSensing<A>,
728    /// }
729    /// ```
730    fn neighbor_sensing_other_attributes() {}
731}
732
733#[cfg(test)]
734mod test_derive_aux_storage {
735    use super::*;
736    use cellular_raza_core_proc_macro::AuxStorage;
737
738    #[derive(AuxStorage)]
739    struct TestStructDouble<Pos, Vel, For, const N: usize> {
740        #[UpdateCycle]
741        aux_cycle: AuxStorageCycle,
742        #[UpdateMechanics(Pos, Vel, For, N)]
743        aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
744    }
745
746    #[derive(AuxStorage)]
747    struct TestStructCycle {
748        #[UpdateCycle]
749        aux_cycle: AuxStorageCycle,
750    }
751
752    #[derive(AuxStorage)]
753    struct TestStructMechanics<Pos, Vel, For, const N: usize> {
754        #[UpdateMechanics(Pos, Vel, For, N)]
755        aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
756    }
757
758    fn add_get_events<A>(aux_storage: &mut A)
759    where
760        A: UpdateCycle,
761    {
762        aux_storage.add_cycle_event(CycleEvent::Division);
763        let events = aux_storage.get_cycle_events();
764        assert_eq!(events, &vec![CycleEvent::Division]);
765    }
766
767    fn set_get_events<A>(aux_storage: &mut A)
768    where
769        A: UpdateCycle,
770    {
771        let initial_events = vec![
772            CycleEvent::Division,
773            CycleEvent::Division,
774            CycleEvent::PhasedDeath,
775        ];
776        aux_storage.set_cycle_events(initial_events.clone());
777        let events = aux_storage.get_cycle_events();
778        assert_eq!(events.len(), 3);
779        assert_eq!(events, &initial_events);
780    }
781
782    #[test]
783    fn cycle_add_get_events() {
784        let mut aux_storage = TestStructCycle {
785            aux_cycle: AuxStorageCycle::default(),
786        };
787        add_get_events(&mut aux_storage);
788    }
789
790    #[test]
791    fn cycle_set_get_events() {
792        let mut aux_storage = TestStructCycle {
793            aux_cycle: AuxStorageCycle::default(),
794        };
795        set_get_events(&mut aux_storage);
796    }
797
798    #[test]
799    fn mechanics() {
800        let mut aux_storage = TestStructMechanics::<_, _, _, 4> {
801            aux_mechanics: AuxStorageMechanics::default(),
802        };
803        aux_storage.set_last_position(3_f64);
804        aux_storage.set_last_velocity(5_f32);
805        aux_storage.add_force(1_f32);
806    }
807
808    #[test]
809    fn cycle_mechanics_add_get_events() {
810        let mut aux_storage = TestStructDouble::<_, _, _, 4> {
811            aux_cycle: AuxStorageCycle::default(),
812            aux_mechanics: AuxStorageMechanics::default(),
813        };
814        aux_storage.set_last_position(3_f64);
815        aux_storage.set_last_velocity(5_f32);
816        aux_storage.add_force(-5_f32);
817        add_get_events(&mut aux_storage);
818    }
819
820    #[test]
821    fn cycle_mechanics_set_get_events() {
822        let mut aux_storage = TestStructDouble::<_, _, _, 4> {
823            aux_cycle: AuxStorageCycle::default(),
824            aux_mechanics: AuxStorageMechanics::default(),
825        };
826        aux_storage.set_last_position(3_f64);
827        aux_storage.set_last_velocity(5_f32);
828        aux_storage.add_force(111_i64);
829        set_get_events(&mut aux_storage);
830    }
831}
832
833#[allow(unused)]
834#[doc(hidden)]
835mod test_build_aux_storage {
836    use crate::backend::chili::proc_macro::aux_storage_constructor;
837    macro_rules! construct (
838        (name:$test_name:ident,
839        aspects:[$($asp:ident),*]) => {
840            /// ```
841            /// use serde::{Deserialize, Serialize};
842            /// use cellular_raza_core::backend::chili::*;
843            /// build_aux_storage!(
844            #[doc = concat!("aspects: [", $(stringify!($asp,),)* "],")]
845            ///     aux_storage_name: __cr_AuxStorage,
846            ///     core_path: cellular_raza_core
847            /// );
848            // #[doc = concat!("let mut aux_storage = __cr_AuxStorage {", init!($($asp),*) "};")]
849            // #[doc = init!{@start $($asp),* end}]
850            #[doc = concat!(
851                "let mut aux_storage = (",
852                stringify!(aux_storage_constructor!(
853                    aux_storage_name: __cr_AuxStorage,
854                    core_path: cellular_raza_core,
855                    aspects: [$($asp),*],
856                )),
857                ")(());",
858            )]
859            /// macro_rules! test_aspect (
860            ///     (Mechanics) => {
861            ///         {
862            ///             use cellular_raza_core::backend::chili::UpdateMechanics;
863            ///             aux_storage.set_last_position(1_f32);
864            ///             aux_storage.set_last_position(3_f32);
865            ///             let last_positions = aux_storage
866            ///                 .previous_positions()
867            ///                 .map(|f| *f)
868            ///                 .collect::<Vec<f32>>();
869            ///             assert_eq!(last_positions, vec![1_f32, 3_f32]);
870            ///             aux_storage.set_last_velocity(10_f32);
871            ///             let last_velocities: cellular_raza_core::backend::chili::RingBufferIterRef<_, 4>
872            ///                 = aux_storage.previous_velocities();
873            ///             let last_velocities = last_velocities.map(|f| *f).collect::<Vec<f32>>();
874            ///             assert_eq!(last_velocities, vec![10_f32]);
875            ///             aux_storage.add_force(22_f32);
876            ///             assert_eq!(aux_storage.get_current_force_and_reset(), 22_f32);
877            ///         }
878            ///     };
879            ///     (Interaction) => {};
880            ///     (NeighborSensing) => {
881            ///         {
882            ///             use cellular_raza_core::backend::chili::UpdateNeighborSensing;
883            ///             let mut acc: &mut Vec<usize> = aux_storage.get_accumulator();
884            ///             acc.push(1);
885            ///             assert_eq!(*aux_storage.get_accumulator(), vec![1]);
886            ///         }
887            ///     };
888            ///     (Cycle) => {
889            ///         {
890            ///             use cellular_raza_core::backend::chili::UpdateCycle;
891            ///             use cellular_raza_concepts::CycleEvent;
892            ///             aux_storage.add_cycle_event(CycleEvent::Division);
893            ///             assert_eq!(aux_storage.get_cycle_events(), &vec![CycleEvent::Division]);
894            ///         }
895            ///     };
896            ///     (Reactions) => {
897            ///         {
898            ///             use cellular_raza_core::backend::chili::UpdateReactions;
899            ///             aux_storage.set_conc(0_f32);
900            ///             aux_storage.incr_conc(1.44_f32);
901            ///             assert_eq!(aux_storage.get_conc(), 0_f32 + 1.44_f32);
902            ///         }
903            ///     };
904            ///     (ReactionsContact) => {
905            ///         {
906            ///             use cellular_raza_core::backend::chili::UpdateReactionsContact;
907            ///             aux_storage.set_last_increment(0f32);
908            ///             aux_storage.set_last_increment(3f32);
909            ///             assert_eq!(UpdateReactionsContact::n_previous_values(&aux_storage), 2);
910            ///             let last_increments =
911            ///                 UpdateReactionsContact::<f32, 10>::previous_increments(
912            ///                 &aux_storage
913            ///             );
914            ///             let last_increments = last_increments.map(|f| *f).collect::<Vec<_>>();
915            ///             assert_eq!(last_increments, vec![0.0, 3.0]);
916            ///         }
917            ///     };
918            /// );
919            #[doc = concat!($(
920                concat!("test_aspect!(", stringify!($asp), ");")
921            ,)*)]
922            /// ```
923            fn $test_name() {}
924        }
925    );
926
927    cellular_raza_core_proc_macro::run_test_for_aspects!(
928        test: construct,
929        aspects: [Mechanics, Interaction, NeighborSensing, Cycle, Reactions, ReactionsContact]
930    );
931}