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}