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-Interaction -------------------------------
318/// Interface to store intermediate information about interactions.
319pub trait UpdateInteraction {
320    /// Obtain current number of neighbors
321    fn get_current_neighbors(&self) -> usize;
322    /// Set the number of neighbors
323    fn set_current_neighbors(&mut self, neighbors: usize);
324    /// Increment the number of current neighbors by the provided value
325    fn incr_current_neighbors(&mut self, neighbors: usize);
326}
327
328/// Helper storage for number of neighbors of
329/// [Interaction](cellular_raza_concepts::Interaction) trait.
330#[derive(Clone, Default, Deserialize, Serialize)]
331pub struct AuxStorageInteraction {
332    neighbor_count: usize,
333}
334
335impl UpdateInteraction for AuxStorageInteraction {
336    #[inline]
337    fn get_current_neighbors(&self) -> usize {
338        self.neighbor_count
339    }
340
341    #[inline]
342    fn incr_current_neighbors(&mut self, neighbors: usize) {
343        self.neighbor_count += neighbors;
344    }
345
346    #[inline]
347    fn set_current_neighbors(&mut self, neighbors: usize) {
348        self.neighbor_count = neighbors;
349    }
350}
351
352#[allow(unused)]
353#[doc(hidden)]
354mod test_derive_aux_storage_compile {
355    /// ```
356    /// use cellular_raza_core::backend::chili::AuxStorage;
357    /// use cellular_raza_core::backend::chili::*;
358    ///
359    /// #[derive(AuxStorage)]
360    /// struct TestStructMechanics<Pos, Vel, For, const N: usize> {
361    ///     #[UpdateMechanics(Pos, Vel, For, N)]
362    ///     aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
363    /// }
364    /// ```
365    fn mechanics_default() {}
366
367    /// ```
368    /// use cellular_raza_core::backend::chili::AuxStorage;
369    /// use cellular_raza_core::backend::chili::*;
370    ///
371    /// #[derive(AuxStorage)]
372    /// pub struct TestStructMechanics<Pos, Vel, For, const N: usize> {
373    ///     #[UpdateMechanics(Pos, Vel, For, N)]
374    ///     aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
375    /// }
376    /// ```
377    fn mechanics_visibility_1() {}
378
379    /// ```
380    /// use cellular_raza_core::backend::chili::AuxStorage;
381    /// use cellular_raza_core::backend::chili::*;
382    ///
383    /// #[derive(AuxStorage)]
384    /// pub(crate) struct TestStructMechanics<Pos, Vel, For, const N: usize> {
385    ///     #[UpdateMechanics(Pos, Vel, For, N)]
386    ///     aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
387    /// }
388    /// ```
389    fn mechanics_visibility_2() {}
390
391    /// ```
392    /// mod some_module {
393    ///     use cellular_raza_core::backend::chili::AuxStorage;
394    ///     use cellular_raza_core::backend::chili::*;
395    ///
396    ///     #[derive(AuxStorage)]
397    ///     pub(super) struct TestStructMechanics<Pos, Vel, For, const N: usize> {
398    ///         #[UpdateMechanics(Pos, Vel, For, N)]
399    ///         aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
400    ///     }
401    /// }
402    /// fn use_impl<T, Pos, Vel, For, const N: usize>(
403    ///     mut aux_storage: T
404    /// ) -> For
405    /// where
406    ///     T: cellular_raza_core::backend::chili::UpdateMechanics<Pos, Vel, For, N>,
407    /// {
408    ///     aux_storage.get_current_force_and_reset()
409    /// }
410    /// ```
411    fn mechanics_visibility_3() {}
412
413    /// ```
414    /// use cellular_raza_core::backend::chili::AuxStorage;
415    /// use cellular_raza_core::backend::chili::*;
416    ///
417    /// #[derive(AuxStorage)]
418    /// struct TestStructMechanics<Pos, Vel, For, T, const N: usize> {
419    ///     #[UpdateMechanics(Pos, Vel, For, N)]
420    ///     aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
421    ///     other: T,
422    /// }
423    /// ```
424    fn mechanics_more_struct_generics() {}
425
426    /// ```
427    /// use cellular_raza_core::backend::chili::AuxStorage;
428    /// use cellular_raza_core::backend::chili::*;
429    ///
430    /// #[derive(AuxStorage)]
431    /// struct TestStructMechanics<Pos, Vel, For, const N: usize, const M: usize> {
432    ///     #[UpdateMechanics(Pos, Vel, For, N)]
433    ///     aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
434    ///     count: [i64; M],
435    /// }
436    /// ```
437    fn mechanics_more_struct_const_generics() {}
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    /// where
446    ///     Pos: Clone,
447    /// {
448    ///     #[UpdateMechanics(Pos, Vel, For, N)]
449    ///     aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
450    /// }
451    /// ```
452    fn mechanics_where_clause() {}
453
454    /// ```
455    /// use cellular_raza_core::backend::chili::AuxStorage;
456    /// use cellular_raza_core::backend::chili::*;
457    ///
458    /// #[derive(AuxStorage)]
459    /// struct TestStructMechanics<Pos, Vel, For, const N: usize> {
460    ///     #[UpdateMechanics(Pos, Vel, For, N)]
461    ///     #[cfg(not(test))]
462    ///     aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
463    /// }
464    /// ```
465    fn mechanics_other_attributes() {}
466
467    /// ```
468    /// use cellular_raza_core::backend::chili::AuxStorage;
469    /// use cellular_raza_core::backend::chili::*;
470    /// use cellular_raza_concepts::CycleEvent;
471    ///
472    /// #[derive(AuxStorage)]
473    /// struct TestStructCycle {
474    ///     #[UpdateCycle]
475    ///     aux_cycle: AuxStorageCycle,
476    /// }
477    /// ```
478    fn cycle_default() {}
479
480    /// ```
481    /// use cellular_raza_core::backend::chili::AuxStorage;
482    /// use cellular_raza_core::backend::chili::*;
483    /// use cellular_raza_concepts::CycleEvent;
484    ///
485    /// #[derive(AuxStorage)]
486    /// pub struct TestStructCycle {
487    ///     #[UpdateCycle]
488    ///     aux_cycle: AuxStorageCycle,
489    /// }
490    /// ```
491    fn cycle_visibility_1() {}
492
493    /// ```
494    /// use cellular_raza_core::backend::chili::AuxStorage;
495    /// use cellular_raza_core::backend::chili::*;
496    /// use cellular_raza_concepts::CycleEvent;
497    ///
498    /// #[derive(AuxStorage)]
499    /// pub(crate) struct TestStructCycle {
500    ///     #[UpdateCycle]
501    ///     aux_cycle: AuxStorageCycle,
502    /// }
503    /// ```
504    fn cycle_visibility_2() {}
505
506    /// ```
507    /// use cellular_raza_core::backend::chili::AuxStorage;
508    /// use cellular_raza_core::backend::chili::*;
509    /// use cellular_raza_concepts::CycleEvent;
510    ///
511    /// #[derive(AuxStorage)]
512    /// pub struct TestStructCycle<T> {
513    ///     #[UpdateCycle]
514    ///     aux_cycle: AuxStorageCycle,
515    ///     _generic: T,
516    /// }
517    /// ```
518    fn cycle_generic_param() {}
519
520    /// ```
521    /// use cellular_raza_core::backend::chili::AuxStorage;
522    /// use cellular_raza_core::backend::chili::*;
523    /// use cellular_raza_concepts::CycleEvent;
524    ///
525    /// #[derive(AuxStorage)]
526    /// pub struct TestStructCycle<const N: usize> {
527    ///     #[UpdateCycle]
528    ///     aux_cycle: AuxStorageCycle,
529    ///     _generic: [f64; N],
530    /// }
531    /// ```
532    fn cycle_const_generic_param() {}
533
534    /// ```
535    /// use cellular_raza_core::backend::chili::AuxStorage;
536    /// use cellular_raza_core::backend::chili::*;
537    /// use cellular_raza_concepts::CycleEvent;
538    ///
539    /// #[derive(AuxStorage)]
540    /// pub struct TestStructCycle<T>
541    /// where
542    ///     T: Clone,
543    /// {
544    ///     #[UpdateCycle]
545    ///     aux_cycle: AuxStorageCycle,
546    ///     _generic: T,
547    /// }
548    /// ```
549    fn cycle_where_clause() {}
550
551    /// ```
552    /// use cellular_raza_core::backend::chili::AuxStorage;
553    /// use cellular_raza_core::backend::chili::*;
554    /// use cellular_raza_concepts::CycleEvent;
555    ///
556    /// #[derive(AuxStorage)]
557    /// struct TestStructCycle {
558    ///     #[UpdateCycle]
559    ///     #[cfg(not(test))]
560    ///     aux_cycle: AuxStorageCycle,
561    /// }
562    /// ```
563    fn cycle_other_attributes() {}
564
565    /// ```
566    /// use cellular_raza_core::backend::chili::AuxStorage;
567    /// use cellular_raza_core::backend::chili::*;
568    ///
569    /// #[derive(AuxStorage)]
570    /// struct TestStructReactions<R> {
571    ///     #[UpdateReactions(R)]
572    ///     aux_cycle: AuxStorageReactions<R>,
573    /// }
574    /// ```
575    fn reactions_default() {}
576
577    /// ```
578    /// use cellular_raza_core::backend::chili::AuxStorage;
579    /// use cellular_raza_core::backend::chili::*;
580    ///
581    /// #[derive(AuxStorage)]
582    /// pub struct TestStructReactions<R> {
583    ///     #[UpdateReactions(R)]
584    ///     aux_cycle: AuxStorageReactions<R>,
585    /// }
586    /// ```
587    fn reactions_visibility_1() {}
588
589    /// ```
590    /// use cellular_raza_core::backend::chili::AuxStorage;
591    /// use cellular_raza_core::backend::chili::*;
592    ///
593    /// #[derive(AuxStorage)]
594    /// pub(crate) struct TestStructReactions<R> {
595    ///     #[UpdateReactions(R)]
596    ///     aux_cycle: AuxStorageReactions<R>,
597    /// }
598    /// ```
599    fn reactions_visibility_2() {}
600
601    /// ```
602    /// use cellular_raza_core::backend::chili::AuxStorage;
603    /// use cellular_raza_core::backend::chili::*;
604    ///
605    /// #[derive(AuxStorage)]
606    /// struct TestStructReactions<T, R> {
607    ///     #[UpdateReactions(R)]
608    ///     aux_cycle: AuxStorageReactions<R>,
609    ///     generic: T,
610    /// }
611    /// ```
612    fn reactions_generic_param() {}
613
614    /// ```
615    /// use cellular_raza_core::backend::chili::AuxStorage;
616    /// use cellular_raza_core::backend::chili::*;
617    ///
618    /// #[derive(AuxStorage)]
619    /// struct TestStructReactions<R, const N: usize> {
620    ///     #[UpdateReactions(R)]
621    ///     aux_cycle: AuxStorageReactions<R>,
622    ///     generic_array: [usize; N],
623    /// }
624    /// ```
625    fn reactions_const_generic_param() {}
626
627    /// ```
628    /// use cellular_raza_core::backend::chili::AuxStorage;
629    /// use cellular_raza_core::backend::chili::*;
630    ///
631    /// #[derive(AuxStorage)]
632    /// struct TestStructReactions<T, R>
633    /// where
634    ///     T: Clone,
635    /// {
636    ///     #[UpdateReactions(R)]
637    ///     aux_cycle: AuxStorageReactions<R>,
638    ///     generic: T,
639    /// }
640    /// ```
641    fn reactions_where_clause() {}
642
643    /// ```
644    /// use cellular_raza_core::backend::chili::AuxStorage;
645    /// use cellular_raza_core::backend::chili::*;
646    ///
647    /// #[derive(AuxStorage)]
648    /// struct TestStructReactions<R> {
649    ///     #[cfg(not(test))]
650    ///     #[UpdateReactions(R)]
651    ///     aux_cycle: AuxStorageReactions<R>,
652    /// }
653    /// ```
654    fn reactions_other_attributes() {}
655
656    /// ```
657    /// use cellular_raza_core::backend::chili::AuxStorage;
658    /// use cellular_raza_core::backend::chili::*;
659    ///
660    /// #[derive(AuxStorage)]
661    /// struct TestStructInteraction {
662    ///     #[UpdateInteraction]
663    ///     aux_interaction: AuxStorageInteraction,
664    /// }
665    /// ```
666    fn interactions_default() {}
667
668    /// ```
669    /// use cellular_raza_core::backend::chili::AuxStorage;
670    /// use cellular_raza_core::backend::chili::*;
671    ///
672    /// #[derive(AuxStorage)]
673    /// pub struct TestStructInteraction {
674    ///     #[UpdateInteraction]
675    ///     aux_interaction: AuxStorageInteraction,
676    /// }
677    /// ```
678    fn interactions_visibility_1() {}
679
680    /// ```
681    /// use cellular_raza_core::backend::chili::AuxStorage;
682    /// use cellular_raza_core::backend::chili::*;
683    ///
684    /// #[derive(AuxStorage)]
685    /// pub(crate) struct TestStructInteraction {
686    ///     #[UpdateInteraction]
687    ///     aux_interaction: AuxStorageInteraction,
688    /// }
689    /// ```
690    fn interactions_visibility_2() {}
691
692    /// ```
693    /// use cellular_raza_core::backend::chili::AuxStorage;
694    /// use cellular_raza_core::backend::chili::*;
695    ///
696    /// #[derive(AuxStorage)]
697    /// struct TestStructInteraction<T> {
698    ///     #[UpdateInteraction]
699    ///     aux_interaction: AuxStorageInteraction,
700    ///     generic: T,
701    /// }
702    /// ```
703    fn interactions_generic_param() {}
704
705    /// ```
706    /// use cellular_raza_core::backend::chili::AuxStorage;
707    /// use cellular_raza_core::backend::chili::*;
708    ///
709    /// #[derive(AuxStorage)]
710    /// struct TestStructInteraction<const N: usize> {
711    ///     #[UpdateInteraction]
712    ///     aux_interaction: AuxStorageInteraction,
713    ///     generic: [f64; N],
714    /// }
715    /// ```
716    fn interactions_const_generic_param() {}
717
718    /// ```
719    /// use cellular_raza_core::backend::chili::AuxStorage;
720    /// use cellular_raza_core::backend::chili::*;
721    ///
722    /// #[derive(AuxStorage)]
723    /// struct TestStructInteraction<T>
724    /// where
725    ///     T: Clone,
726    /// {
727    ///     #[UpdateInteraction]
728    ///     aux_interaction: AuxStorageInteraction,
729    ///     generic: T,
730    /// }
731    /// ```
732    fn interactions_where_clause() {}
733
734    /// ```
735    /// use cellular_raza_core::backend::chili::AuxStorage;
736    /// use cellular_raza_core::backend::chili::*;
737    ///
738    /// #[derive(AuxStorage)]
739    /// struct TestStructInteraction {
740    ///     #[UpdateInteraction]
741    ///     #[cfg(not(test))]
742    ///     aux_interaction: AuxStorageInteraction,
743    /// }
744    /// ```
745    fn interactions_other_attributes() {}
746}
747
748#[cfg(test)]
749mod test_derive_aux_storage {
750    use super::*;
751    use cellular_raza_core_proc_macro::AuxStorage;
752
753    #[derive(AuxStorage)]
754    struct TestStructDouble<Pos, Vel, For, const N: usize> {
755        #[UpdateCycle]
756        aux_cycle: AuxStorageCycle,
757        #[UpdateMechanics(Pos, Vel, For, N)]
758        aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
759    }
760
761    #[derive(AuxStorage)]
762    struct TestStructCycle {
763        #[UpdateCycle]
764        aux_cycle: AuxStorageCycle,
765    }
766
767    #[derive(AuxStorage)]
768    struct TestStructMechanics<Pos, Vel, For, const N: usize> {
769        #[UpdateMechanics(Pos, Vel, For, N)]
770        aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
771    }
772
773    fn add_get_events<A>(aux_storage: &mut A)
774    where
775        A: UpdateCycle,
776    {
777        aux_storage.add_cycle_event(CycleEvent::Division);
778        let events = aux_storage.get_cycle_events();
779        assert_eq!(events, &vec![CycleEvent::Division]);
780    }
781
782    fn set_get_events<A>(aux_storage: &mut A)
783    where
784        A: UpdateCycle,
785    {
786        let initial_events = vec![
787            CycleEvent::Division,
788            CycleEvent::Division,
789            CycleEvent::PhasedDeath,
790        ];
791        aux_storage.set_cycle_events(initial_events.clone());
792        let events = aux_storage.get_cycle_events();
793        assert_eq!(events.len(), 3);
794        assert_eq!(events, &initial_events);
795    }
796
797    #[test]
798    fn cycle_add_get_events() {
799        let mut aux_storage = TestStructCycle {
800            aux_cycle: AuxStorageCycle::default(),
801        };
802        add_get_events(&mut aux_storage);
803    }
804
805    #[test]
806    fn cycle_set_get_events() {
807        let mut aux_storage = TestStructCycle {
808            aux_cycle: AuxStorageCycle::default(),
809        };
810        set_get_events(&mut aux_storage);
811    }
812
813    #[test]
814    fn mechanics() {
815        let mut aux_storage = TestStructMechanics::<_, _, _, 4> {
816            aux_mechanics: AuxStorageMechanics::default(),
817        };
818        aux_storage.set_last_position(3_f64);
819        aux_storage.set_last_velocity(5_f32);
820        aux_storage.add_force(1_f32);
821    }
822
823    #[test]
824    fn cycle_mechanics_add_get_events() {
825        let mut aux_storage = TestStructDouble::<_, _, _, 4> {
826            aux_cycle: AuxStorageCycle::default(),
827            aux_mechanics: AuxStorageMechanics::default(),
828        };
829        aux_storage.set_last_position(3_f64);
830        aux_storage.set_last_velocity(5_f32);
831        aux_storage.add_force(-5_f32);
832        add_get_events(&mut aux_storage);
833    }
834
835    #[test]
836    fn cycle_mechanics_set_get_events() {
837        let mut aux_storage = TestStructDouble::<_, _, _, 4> {
838            aux_cycle: AuxStorageCycle::default(),
839            aux_mechanics: AuxStorageMechanics::default(),
840        };
841        aux_storage.set_last_position(3_f64);
842        aux_storage.set_last_velocity(5_f32);
843        aux_storage.add_force(111_i64);
844        set_get_events(&mut aux_storage);
845    }
846}
847
848#[allow(unused)]
849#[doc(hidden)]
850mod test_build_aux_storage {
851    use crate::backend::chili::proc_macro::aux_storage_constructor;
852    macro_rules! construct (
853        (name:$test_name:ident,
854        aspects:[$($asp:ident),*]) => {
855            /// ```
856            /// use serde::{Deserialize, Serialize};
857            /// use cellular_raza_core::backend::chili::*;
858            /// build_aux_storage!(
859            #[doc = concat!("aspects: [", $(stringify!($asp,),)* "],")]
860            ///     aux_storage_name: __cr_AuxStorage,
861            ///     core_path: cellular_raza_core
862            /// );
863            // #[doc = concat!("let mut aux_storage = __cr_AuxStorage {", init!($($asp),*) "};")]
864            // #[doc = init!{@start $($asp),* end}]
865            #[doc = concat!(
866                "let mut aux_storage = (",
867                stringify!(aux_storage_constructor!(
868                    aux_storage_name: __cr_AuxStorage,
869                    core_path: cellular_raza_core,
870                    aspects: [$($asp),*],
871                )),
872                ")(());",
873            )]
874            /// macro_rules! test_aspect (
875            ///     (Mechanics) => {
876            ///         {
877            ///             use cellular_raza_core::backend::chili::UpdateMechanics;
878            ///             aux_storage.set_last_position(1_f32);
879            ///             aux_storage.set_last_position(3_f32);
880            ///             let last_positions = aux_storage
881            ///                 .previous_positions()
882            ///                 .map(|f| *f)
883            ///                 .collect::<Vec<f32>>();
884            ///             assert_eq!(last_positions, vec![1_f32, 3_f32]);
885            ///             aux_storage.set_last_velocity(10_f32);
886            ///             let last_velocities: cellular_raza_core::backend::chili::RingBufferIterRef<_, 4>
887            ///                 = aux_storage.previous_velocities();
888            ///             let last_velocities = last_velocities.map(|f| *f).collect::<Vec<f32>>();
889            ///             assert_eq!(last_velocities, vec![10_f32]);
890            ///             aux_storage.add_force(22_f32);
891            ///             assert_eq!(aux_storage.get_current_force_and_reset(), 22_f32);
892            ///         }
893            ///     };
894            ///     (Interaction) => {
895            ///         {
896            ///             use cellular_raza_core::backend::chili::UpdateInteraction;
897            ///             aux_storage.incr_current_neighbors(1);
898            ///             aux_storage.incr_current_neighbors(2);
899            ///             aux_storage.incr_current_neighbors(1);
900            ///             assert_eq!(aux_storage.get_current_neighbors(), 4);
901            ///         }
902            ///     };
903            ///     (Cycle) => {
904            ///         {
905            ///             use cellular_raza_core::backend::chili::UpdateCycle;
906            ///             use cellular_raza_concepts::CycleEvent;
907            ///             aux_storage.add_cycle_event(CycleEvent::Division);
908            ///             assert_eq!(aux_storage.get_cycle_events(), &vec![CycleEvent::Division]);
909            ///         }
910            ///     };
911            ///     (Reactions) => {
912            ///         {
913            ///             use cellular_raza_core::backend::chili::UpdateReactions;
914            ///             aux_storage.set_conc(0_f32);
915            ///             aux_storage.incr_conc(1.44_f32);
916            ///             assert_eq!(aux_storage.get_conc(), 0_f32 + 1.44_f32);
917            ///         }
918            ///     };
919            ///     (ReactionsContact) => {
920            ///         {
921            ///             use cellular_raza_core::backend::chili::UpdateReactionsContact;
922            ///             aux_storage.set_last_increment(0f32);
923            ///             aux_storage.set_last_increment(3f32);
924            ///             assert_eq!(UpdateReactionsContact::n_previous_values(&aux_storage), 2);
925            ///             let last_increments =
926            ///                 UpdateReactionsContact::<f32, 10>::previous_increments(
927            ///                 &aux_storage
928            ///             );
929            ///             let last_increments = last_increments.map(|f| *f).collect::<Vec<_>>();
930            ///             assert_eq!(last_increments, vec![0.0, 3.0]);
931            ///         }
932            ///     };
933            /// );
934            #[doc = concat!($(
935                concat!("test_aspect!(", stringify!($asp), ");")
936            ,)*)]
937            /// ```
938            fn $test_name() {}
939        }
940    );
941
942    cellular_raza_core_proc_macro::run_test_for_aspects!(
943        test: construct,
944        aspects: [Mechanics, Interaction, Cycle, Reactions, ReactionsContact]
945    );
946}