cellular_raza_concepts/
domain_old.rs

1use crate::cell::CellBox;
2use crate::errors::*;
3
4use core::hash::Hash;
5use std::ops::{Add, Mul};
6
7use num::Zero;
8use serde::{Deserialize, Serialize};
9
10use super::cycle::CycleEvent;
11
12/// Describes the physical simulation domain.
13///
14/// This trait is responsible for the overall physical setup of our simulation.
15/// Simple domains can be thought of as rectangular cuboids in 2D or 3D and such examples
16/// are being implemented in [domains](https://docs.rs/cellular_raza-building-blocks::domains).
17/// Most of the functions you will see are required by the backend to make sense of the whole simulation domain and
18/// send cells to the correct subdomains and give correct boundary conditions.
19/// [cellular_raza](https://docs.rs/cellular_raza) uses [domain decomposition](https://wikipedia.org/wiki/Domain_decomposition_methods)
20/// to parallelize over different regions of space and thus efficiently utilize hardware resources
21/// although the exact details do depend on the [backend](https://docs.rs/cellular_raza-core/backend/).
22/// The simulation domain is split into many voxels which interact only with their next neighbors.
23/// By increasing the size of these voxels, we can allow for longer interaction ranges or vice versa.
24pub trait Domain<C, I, V>: Send + Sync + Serialize + for<'a> Deserialize<'a> {
25    /// Applies boundary conditions to a cell in order to keep it inside the simulation.
26    /// For the future, we aim to apply boundary conditions to the position of the cell rather than itself.
27    /// In addition, we would like to be able to invoke events such as [Remove](super::cycle::CycleEvent::Remove) to maximize flexibility.
28    fn apply_boundary(&self, cell: &mut C) -> Result<(), BoundaryError>;
29
30    /// Retrieves the neighboring voxels of the one specified.
31    fn get_neighbor_voxel_indices(&self, index: &I) -> Vec<I>;
32
33    /// Provided a cell, gives the corresponding Index and thus which voxel to sort into.
34    fn get_voxel_index(&self, cell: &C) -> I;
35
36    /// Get all indices that are present in the simulation. Required for initial configuration of the simulation domain.
37    fn get_all_indices(&self) -> Vec<I>;
38    // TODO rename this function and generate SubDomains which then hold a number of voxels.
39    // These subdomains should also be responsible to integrate extracellular mechanics and so on.
40    // This is already partly realized by MultivoxelContainers in the domain_decomposition module of the cpu_os_threads backend.
41    /// Allows the backend to split the domain into continuous regions which contain voxels.
42    /// These regions can then be used for parallelization.
43    fn generate_contiguous_multi_voxel_regions(
44        &self,
45        n_regions: usize,
46    ) -> Result<Vec<Vec<(I, V)>>, CalcError>;
47}
48
49/// The different types of boundary conditions in a PDE system
50/// One has to be careful, since the neumann condition is strictly speaking
51/// not of the same type since its units are multiplied by 1/time compared to the others.
52/// The Value variant is not a boundary condition in the traditional sense but
53/// here used as the value which is present in another voxel.
54#[derive(Serialize, Deserialize, Clone, Debug)]
55pub enum BoundaryCondition<ConcVecExtracellular> {
56    /// Neumann boundary conditions apply a value to the derivative at the corresponding boundary.
57    Neumann(ConcVecExtracellular),
58    /// Dirichlet conditions fix the value of concentration at the boundary.
59    Dirichlet(ConcVecExtracellular),
60    /// This boundary condition fixes the value at boundary. Although in principle exactly the same as [BoundaryCondition::Dirichlet],
61    /// this value is not provided by the user but rather the boundary condition of another simulation subdomain.
62    Value(ConcVecExtracellular),
63}
64
65// TODO migrate to trait alias when stabilized
66// pub trait Index = Ord + Hash + Eq + Clone + Send + Sync + Serialize + std::fmt::Debug;
67/// Summarizes traits required for an [Index] of a [Domain] to work.
68pub trait Index: Ord + Hash + Eq + Clone + Send + Sync + Serialize + std::fmt::Debug {}
69impl<T> Index for T where T: Ord + Hash + Eq + Clone + Send + Sync + Serialize + std::fmt::Debug {}
70
71/* pub trait Concentration =
72Sized + Add<Self, Output = Self> + Mul<f64, Output = Self> + Send + Sync + Zero;*/
73/// Preliminary traits to model external [Concentration] in respective [Voxel].
74pub trait Concentration:
75    Sized + Add<Self, Output = Self> + Mul<f64, Output = Self> + Send + Sync + Zero
76{
77}
78impl<T> Concentration for T where
79    T: Sized + Add<Self, Output = Self> + Mul<f64, Output = Self> + Send + Sync + Zero
80{
81}
82
83/// The [Domain] trait generalizes over the [Voxel] generic parameter which
84pub trait Voxel<Ind, Pos, Vel, Force>:
85    Send + Sync + Clone + Serialize + for<'a> Deserialize<'a>
86{
87    /// Voxels can exert custom forces on cells. In the future this function will probably be part of a different Trait.
88    fn custom_force_on_cell(&self, _pos: &Pos, _vel: &Vel) -> Option<Result<Force, CalcError>> {
89        None
90    }
91
92    /// Gets the Index of the voxel.
93    fn get_index(&self) -> Ind;
94}
95
96// TODO these functions do NOT capture possible implementations accurately
97// In principle we should differentiate between
98//      - total concentrations everywhere in domain
99//          - some kind of additive/iterable multi-dimensional array
100//          - eg. in cartesian 2d: (n1,n2,m) array where n1,n2 are the number of sub-voxels and m the number of different concentrations
101//      - concentrations at a certain point
102//          - some kind of vector with entries corresponding to the individual concentrations
103//          - should be a slice of the total type
104//      - boundary conditions to adjacent voxels
105//          - some kind of multi-dimensional array with one dimension less than the total concentrations
106//          - should be a slice of the total type
107// In the future we hope to use https://doc.rust-lang.org/std/slice/struct.ArrayChunks.html
108
109// This is currently only a trait valid for n types of concentrations which are constant across the complete voxel
110// Functions related to diffusion and fluid dynamics of extracellular reactants/ligands
111
112// TODO rework this trait. We do not want to make it dependent on the voxel index. But it may be dependent on spatial representation such as Position type.
113/// First approach on how to generalize over extracellular mechanics.
114/// Future versions will not depend on the [Voxel] [Index] but be more general.
115pub trait ExtracellularMechanics<
116    Ind,
117    Pos,
118    ConcVec,
119    ConcGradient,
120    ConcTotal = ConcVec,
121    ConcBoundary = ConcVec,
122>: Send + Sync + Clone + Serialize + for<'a> Deserialize<'a>
123{
124    /// Obtain the extracellular concentration at a specified point.
125    fn get_extracellular_at_point(&self, pos: &Pos) -> Result<ConcVec, RequestError>;
126
127    /// Obtain every concentration in the current voxel. This function is only relevant for the [backend](https://docs.rs/cellular_raza-core/backend/).
128    fn get_total_extracellular(&self) -> ConcTotal;
129
130    // TODO formulate additional trait which does extracellular gradients mechanics and can be linked to this trait
131    /// Update function to calculate the gradient of concentrations in this voxel.
132    #[cfg(feature = "gradients")]
133    fn update_extracellular_gradient(
134        &mut self,
135        boundaries: &[(Ind, BoundaryCondition<ConcBoundary>)],
136    ) -> Result<(), CalcError>;
137
138    // TODO formulate additional trait which does extracellular gradients mechanics and can be linked to this trait
139    /// Obtain the gradient at a certain point.
140    #[cfg(feature = "gradients")]
141    fn get_extracellular_gradient_at_point(&self, pos: &Pos) -> Result<ConcGradient, RequestError>;
142
143    /// Simple setter function to specify concentrations after backend has updated values.
144    fn set_total_extracellular(&mut self, concentration_total: &ConcTotal)
145    -> Result<(), CalcError>;
146
147    /// Calculates the time-derivative of the function that increments the concentrations.
148    fn calculate_increment(
149        &self,
150        total_extracellular: &ConcTotal,
151        point_sources: &[(Pos, ConcVec)],
152        boundaries: &[(Ind, BoundaryCondition<ConcBoundary>)],
153    ) -> Result<ConcTotal, CalcError>;
154
155    /// Gets the boundary to the specified neighboring voxel.
156    fn boundary_condition_to_neighbor_voxel(
157        &self,
158        neighbor_index: &Ind,
159    ) -> Result<BoundaryCondition<ConcBoundary>, IndexError>;
160}
161
162/// An external controller which can see all of the simulation domain's cells and perform modifications on individual cells.
163/// This controller is only useful when describing systems that are controlled from the outside and not subject to local interactions.
164/// This trait is not finalized yet.
165pub trait Controller<C, O> {
166    /// This function views a part of the simulation domain and retrieves information about the cells contained in it.
167    /// Afterwards, this measurement is stored and then a collection of measurements is provided to the [adjust](Controller::adjust) function.
168    fn measure<'a, I>(&self, cells: I) -> Result<O, CalcError>
169    where
170        C: 'a + Serialize + for<'b> Deserialize<'b>,
171        I: IntoIterator<Item = &'a CellBox<C>> + Clone;
172
173    /// Function that operates on cells given an iterator over measurements. It modifies cellular properties and can invoke [CycleEvenets](super::cycle::CycleEvent).
174    fn adjust<'a, 'b, I, J>(&mut self, measurements: I, cells: J) -> Result<(), ControllerError>
175    where
176        O: 'a,
177        C: 'b + Serialize + for<'c> Deserialize<'c>,
178        I: Iterator<Item = &'a O>,
179        J: Iterator<Item = (&'b mut CellBox<C>, &'b mut Vec<CycleEvent>)>;
180}
181
182impl<C> Controller<C, ()> for () {
183    fn measure<'a, I>(&self, _cells: I) -> Result<(), CalcError>
184    where
185        C: 'a + Serialize + for<'b> Deserialize<'b>,
186        I: IntoIterator<Item = &'a CellBox<C>> + Clone,
187    {
188        Ok(())
189    }
190
191    #[allow(unused)]
192    fn adjust<'a, 'b, I, J>(&mut self, measurements: I, cells: J) -> Result<(), ControllerError>
193    where
194        (): 'a,
195        C: 'b + Serialize + for<'c> Deserialize<'c>,
196        I: Iterator<Item = &'a ()>,
197        J: Iterator<Item = (&'b mut CellBox<C>, &'b mut Vec<CycleEvent>)>,
198    {
199        Ok(())
200    }
201}