CellModules
DiffusionGrid.hpp
Go to the documentation of this file.
1#ifndef ONKO3D_3_0_DIFFUSIONGRID_HPP
2#define ONKO3D_3_0_DIFFUSIONGRID_HPP
3
11#include <vector>
12#include <typeindex>
13#include <typeinfo>
14#include <unordered_map>
16
21namespace Diffusion {
22
27 struct Molecule {
28 static constexpr double spheroidDensity = 0.001;
29 static constexpr double henryConst = 22779000000.;
30 double diffusion;
32 double omega;
42 inline Molecule(double d, double dQ, double density, double dE) : diffusion(d), defaultQuantity(dQ),
44 };
45
50 struct GridCell {
58 inline GridCell() = default;
59
65 int size = m.size();
66 quantities.resize(size);
68 consumptions.assign(size, 0.);
69 for (int i = 0; i < size; ++i) {
70 quantities[i] = m[i].defaultQuantity;
71 prevQuantities[i] = m[i].defaultQuantity;
72 }
73 }
74 };
75
81 private:
82 double dx = 5.;
83 double accuracy = 0.1;
84 unordered_map<MecaCell::Vec, GridCell> grid;
87 // Boundaries
90
98 inline double deriv2nd(double xm1, double x, double xp1) { return ((xm1 - (2.0 * x) + xp1) / (dx * dx)); }
99
104 void nextStep(int i) {
105 for (auto &c : grid) {
106 c.second.prevQuantities[i] = c.second.quantities[i];
107 }
108 }
109
114 for (auto &c : grid) {
115 for (int i = 0; i < molecules.size(); ++i) { // For each molecule
116 c.second.consumptions[i] = 0.;
117 }
118 }
119 }
120
125 for (auto &c: grid) {
126 if (isOutBoundary(c.first)) {
127 grid.erase(c.first);
128 }
129 }
130 }
131
138 return(v.x()<minBoundary.x() || v.y()<minBoundary.y() || v.z()<minBoundary.z() || v.x()>maxBoundary.x() || v.y()>maxBoundary.y() || v.z()>maxBoundary.z());
139 }
140
146 inline double getDt(double D) const { return (dx * dx) / (6 * D); }
147
153 double computeStep(int i) {
154 Molecule m = molecules[i]; // Considered molecule
155 double D = m.diffusion; // Diffusion constant in µm²/s
156 double dt = getDt(D); // Diffusion time step in s
157 double total = 0; // Total amount of considered molecule in mmHg
158 for (auto &c : grid) { // For each cell in the grid
159 GridCell &gc = c.second;
160 double prevQuantities = gc.prevQuantities[i];
161 // Laplacian in mmHg/µm²
162 double laplacian = deriv2nd(getMolecule(c.first - MecaCell::Vec(1, 0, 0), i), prevQuantities,
163 getMolecule(c.first + MecaCell::Vec(1, 0, 0), i)) +
164 deriv2nd(getMolecule(c.first - MecaCell::Vec(0, 1, 0), i), prevQuantities,
165 getMolecule(c.first + MecaCell::Vec(0, 1, 0), i)) +
166 deriv2nd(getMolecule(c.first - MecaCell::Vec(0, 0, 1), i), prevQuantities,
167 getMolecule(c.first + MecaCell::Vec(0, 0, 1), i));
168 gc.quantities[i] = prevQuantities + (D * laplacian - ((gc.consumptions[i] + m.defaultEvaporation) * m.omega)) * dt;
169 if (gc.quantities[i] < 0.) { // Can't have a negative amount of molecule
170 gc.quantities[i] = 0.;
171 }
172 total += gc.quantities[i];
173 }
174 return (total);
175 }
176
177 public:
178
179 unordered_map<int,int> moleculesDict;
184 DiffusionGrid() = default;
185
191 inline DiffusionGrid(double dx, double accuracy) : dx(dx), accuracy(accuracy), grid(), molecules() {}
192
197 inline double getDx() const { return dx; }
198
203 inline void setDx(double _dx) { dx = _dx; }
204
209 inline void setAccuracy(double a) { accuracy = a; }
210
217 MecaCell::Vec res = v / dx;
218 return MecaCell::Vec(floor(res.x()), floor(res.y()), floor(res.z()));
219 }
220
227 double getMolecule(MecaCell::Vec v, int m) {
228 if (grid.count(v) <= 0)
229 return (molecules[m].defaultQuantity);
230 else
231 return(grid[forward<MecaCell::Vec>(v)].quantities[m]);
232 }
233
238 inline size_t size() const { return grid.size(); }
239
244 inline unordered_map<MecaCell::Vec, GridCell> &getGrid() { return grid; }
245
250 inline double getCellSize() const { return dx; }
251
256 inline vector<Molecule> getMolecules() const { return molecules; }
257
263 void addMolecule(int n, Molecule m) {
264 moleculesDict[n] = (int) molecules.size();
265 molecules.push_back(m);
266 }
267
273 template<typename world_t>
274 void updateBoundary(world_t *w) {
275 MecaCell::Vec min(9999,9999,9999);
276 MecaCell::Vec max(-9999,-9999,-9999);
277 allCellEmpty();
278 for (auto &c : w->cells) { // For each cell
279 MecaCell::Vec center = getIndexFromPosition(c->getBody().getPosition());
280
281 // Update min and max boundaries
282 if(center.x()<min.x()) min.setX(center.x());
283 if(center.y()<min.y()) min.setY(center.y());
284 if(center.z()<min.z()) min.setZ(center.z());
285
286 if(center.x()>max.x()) max.setX(center.x());
287 if(center.y()>max.y()) max.setY(center.y());
288 if(center.z()>max.z()) max.setZ(center.z());
289
290 // Update consumptions and create new grid cells
291 if (grid.count(forward<MecaCell::Vec>(center)) <= 0) {
293 for (int i = 0; i < molecules.size(); ++i) { // For each molecule
294 gc.consumptions[i] += c->getBody().getConsumptionByIndex(i);
295 }
296 grid[forward<MecaCell::Vec>(center)] = gc;
297 } else {
298 for (int i = 0; i < molecules.size(); ++i) { // For each molecule
299 grid[forward<MecaCell::Vec>(center)].consumptions[i] += c->getBody().getConsumptionByIndex(i);
300 }
301 }
302 }
303
304 minBoundary = min;
305 maxBoundary = max;
306 for(int x=minBoundary.x();x<maxBoundary.x();x++){
307 for(int y=minBoundary.y();y<maxBoundary.y();y++){
308 for(int z=minBoundary.z();z<maxBoundary.z();z++){
309 MecaCell::Vec pos(x,y,z);
310 if (grid.count(forward<MecaCell::Vec>(pos)) <= 0) {
311 grid[forward<MecaCell::Vec>(pos)] = GridCell(molecules);
312 }
313 }
314 }
315 }
316 }
317
323 template<typename world_t>
324 void computeMolecules(world_t *w) {
325 vector<double> lasts; // Last step quantities
326 vector<double> news; // Current step quantities
327 lasts.assign(molecules.size(),0.);
328 news.assign(molecules.size(), INFINITY);
329 for (int i = 0; i < molecules.size(); ++i) { // For each molecule
330 double t = 0; // Elapsed time
331 double dt = getDt(molecules[i].diffusion); // Diffusion time step
332 while (abs(lasts[i] - news[i]) / grid.size() >= accuracy && t < w->dt) {
333 lasts[i] = news[i];
334 nextStep(i);
335 news[i] = computeStep(i);
336 t += dt;
337 }
338 }
339 }
340
347 inline double getMoleculeRealPos(const MecaCell::Vec &v, int mol) {
348 return (getMolecule(getIndexFromPosition(v), mol));
349 }
350 };
351}
352
353#endif //ONKO3D_3_0_DIFFUSIONGRID_HPP
MecaCell::Vec pos
Definition: CellBody.hpp:34
Class representing a grid for molecule diffusion.
double getDx() const
Gets the grid cell size.
unordered_map< int, int > moleculesDict
double getCellSize() const
Gets the grid cell size.
bool isOutBoundary(const MecaCell::Vec &v)
Checks if a position is out of boundaries.
vector< Molecule > molecules
void setDx(double _dx)
Sets the grid cell size.
double getDt(double D) const
Gets the diffusion time step.
void setAccuracy(double a)
Sets the diffusion accuracy.
void cleanCellOutBoundary()
Cleans cells that are out of boundaries.
size_t size() const
Gets the size of the grid.
DiffusionGrid()=default
Default constructor.
void updateBoundary(world_t *w)
Updates the grid boundaries and consumptions.
void addMolecule(int n, Molecule m)
Adds a molecule to the grid.
double getMoleculeRealPos(const MecaCell::Vec &v, int mol)
Gets the quantity of a molecule at a real position.
MecaCell::Vec getIndexFromPosition(const MecaCell::Vec &v) const
Gets the grid index from a position.
DiffusionGrid(double dx, double accuracy)
Constructor with grid parameters.
unordered_map< MecaCell::Vec, GridCell > & getGrid()
Gets the grid.
unordered_map< MecaCell::Vec, GridCell > grid
double computeStep(int i)
Updates the quantity of a molecule for each cell and returns the total amount of this molecule.
double deriv2nd(double xm1, double x, double xp1)
Calculates the second derivative.
void nextStep(int i)
Initializes the next step for a molecule.
double getMolecule(MecaCell::Vec v, int m)
Gets the quantity of a molecule at a position.
void computeMolecules(world_t *w)
Updates the quantities of molecules in the grid.
vector< Molecule > getMolecules() const
Gets the molecules in the grid.
void allCellEmpty()
Empties all cells.
general purpose 3D vector/point class.
Definition: vector3D.h:20
double x() const
Definition: vector3D.h:94
double y() const
Definition: vector3D.h:100
void setX(const double f)
setter for x coordinate
Definition: vector3D.h:113
void setY(const double f)
setter for y coordinate
Definition: vector3D.h:119
void setZ(const double f)
setter for z coordinate
Definition: vector3D.h:125
double z() const
Definition: vector3D.h:106
void resize(size_t newSize)
Resizes the vector to contain the specified number of elements.
Definition: std.hpp:363
size_t size() const
Returns the number of elements in the vector.
Definition: std.hpp:320
Namespace for diffusion-related structures and classes.
Vector3D Vec
alias for Vector3D
Definition: utils.hpp:22
int abs(int x)
Computes the absolute value of an integer.
Definition: std.hpp:83
double floor(double x)
Computes the floor of a number.
Definition: std.hpp:194
Structure representing a cell in the diffusion grid.
GridCell()=default
Default constructor.
vector< double > prevQuantities
vector< double > consumptions
vector< double > quantities
GridCell(vector< Molecule > m)
Constructor to initialize a grid cell with given molecules.
Structure representing a molecule in the diffusion grid.
static constexpr double spheroidDensity
static constexpr double henryConst
Molecule(double d, double dQ, double density, double dE)
Constructor to initialize a molecule with given parameters.