CellModules
world.hpp
Go to the documentation of this file.
1#ifndef MECACELL_WORLD_H
2#define MECACELL_WORLD_H
3#include <array>
4#include <functional>
5#include <unordered_set>
6#include <utility>
7#include <vector>
8#include "integrators.hpp"
12
13namespace MecaCell {
14
25template <typename Cell, typename Integrator = Euler> class World {
26 private:
27 size_t nbThreads = 0;
28
29 public:
30 using cell_t = Cell;
31 using integrator_t = Integrator;
32 using hook_s = void(World *);
34
35 ThreadPool threadpool; // threadpool that can be used by plugins (and is also used to
36 // parallelize updateBehavior)
37
45 // -------------------------------------
46 // The following code detects if any embedded plugin type is specified and defaults
47 // to the instantiation of a useles byte if not.
48 struct dumb {};
49 template <class, class = MecaCell::void_t<>>
50 struct embedded_plugin_type { // declaration
51 using type = dumb; // defaults to empty type if no embedded plugin is defined
52 };
53 template <class T> // specialization
55 using type = typename T::embedded_plugin_t; // embedded plugin detected
56 };
58 typename embedded_plugin_type<cell_t>::type; // either dumb empty struct or the
59 // plugin type
60 // defined by Cell (if existing)
61 protected:
62 size_t frame = 0;
63 size_t nbAddedCells = 0;
64 size_t updtBhvPeriod = 1;
66 bool shuffleCells = true;
67
72 for (auto i = cells.begin(); i != cells.end();) {
73 if ((*i)->isDead()) {
74 auto tmp = *i;
75 i = cells.erase(i);
76 delete tmp;
77 } else {
78 ++i;
79 }
80 }
81 }
82
83 public:
84 double dt = 1.0 / 100.0;
85 double dtMn = dt/60.;
86 double dtH = dt/3600.;
87
88 cellPlugin_t cellPlugin; // instance of the embedded cell plugin type
89 // (cellPlugin_t default to a dumb char if not specified)
90
92
93 /* HOOKS
94 */
95 DECLARE_HOOK(onAddCell, beginUpdate, preBehaviorUpdate, preDeleteDeadCellsUpdate,
96 postBehaviorUpdate, endUpdate, allForcesAppliedToCells, destructor)
97
98 /* CELLS */
100
109 World(size_t nThreads = 0) : nbThreads(nThreads), threadpool(nThreads) {
111 }
112
120
128 size_t getNbThreads() { return nbThreads; }
129
130 void setNbThreads(size_t n) {
131 nbThreads = n;
133 }
134
135 /**********************************************
136 * HOOKS & PLUGINS *
137 *********************************************/
138
145 void registerHook(const Hooks &h, hook_t f) { hooks[eToUI(h)].push_back(f); }
146
168 template <typename P, typename... Rest>
169 void registerPlugins(P &&p, Rest &&... otherPlugins) {
170 // registerPlugin returns the onRegister hook from the plugin
171 registerPlugin(std::forward<P>(p))(this);
172 registerPlugins(std::forward<Rest>(otherPlugins)...);
173 }
175
180 void clearHooks() {
181 for (auto &h : hooks) h.clear();
182 }
183
184 /**********************************************
185 * GET & SET *
186 *********************************************/
187
193 size_t getNbUpdates() const { return frame; }
194
203 template <typename... Args> Cell *createCell(Args &&... args) {
204 Cell *c = new Cell(std::forward<Args>(args)...);
205 addCell(c);
206 return c;
207 }
208
219 void addCell(Cell *c) {
220 if (c) {
221 c->getBody().setCellPlugin(&cellPlugin);
222 c->setWorld(this);
223 newCells.push_back(c);
224 c->id = nbAddedCells++;
225 }
226 }
227
232 void addNewCells() {
233 if (newCells.size()) {
234 for (auto &f : hooks[eToUI(Hooks::onAddCell)]) f(this);
235 cells.insert(cells.end(), newCells.begin(), newCells.end());
236 newCells.clear();
237 }
238 }
239
245 for (auto &f : hooks[eToUI(Hooks::allForcesAppliedToCells)]) f(this);
246 }
247
256 void setDt(double d) { dt = d; dtMn = d/60.; dtH = d/3600.; }
257 void setDtInS(double d) { dt = d; dtMn = d/60.; dtH = d/3600.; }
258 void setDtInMn(double d) { dt = d*60.; dtMn = d; dtH = d/60.; }
259 void setDtInH(double d) { dt = d*3600.; dtMn = d*60.; dtH = d; }
260 double getDt() const{ return dt; }
261 double getDtInS() const{ return dt; }
262 double getDtInMn() const{ return dtMn; }
263 double getDtInH() const{ return dtH; }
264
265 void setShuffleCells(bool s) { shuffleCells = s; }
266
275
276 size_t getUpdateBehaviorPeriod() const { return updtBhvPeriod; }
277
278
285 std::unordered_set<ordered_pair<cell_t *>> res;
286 for (auto &c : cells) {
287 for (auto &connected : c->getConnectedCells())
288 res.insert(make_ordered_cell_pair(c, connected));
289 }
291 for (auto &r : res) vecRes.push_back(std::make_pair(r.first, r.second));
292 return vecRes;
293 }
294
300 if(shuffleCells) std::shuffle(std::begin(cells), std::end(cells), MecaCell::Config::globalRand());
301 const size_t MIN_CHUNK_SIZE = 2;
302 const double AVG_TASKS_PER_THREAD = 3.0;
304 threadpool.autoChunks(cells, MIN_CHUNK_SIZE, AVG_TASKS_PER_THREAD,
305 [](auto *c) { c->updateBehavior(); });
307 } else
308 for (auto &c : cells) c->updateBehavior();
309 }
310
323 void update() {
324 for (auto &f : hooks[eToUI(Hooks::beginUpdate)]) f(this);
325 for (auto &f : hooks[eToUI(Hooks::preBehaviorUpdate)]) f(this);
327 addNewCells();
328 for (auto &f : hooks[eToUI(Hooks::preDeleteDeadCellsUpdate)]) f(this);
330 for (auto &f : hooks[eToUI(Hooks::postBehaviorUpdate)]) f(this);
331 for (auto &f : hooks[eToUI(Hooks::endUpdate)]) f(this);
332 ++frame;
333 }
334
339 for (auto &f : hooks[eToUI(Hooks::destructor)]) f(this);
340 while (!cells.empty()) delete cells.back(), cells.pop_back();
341 while (!newCells.empty()) delete newCells.back(), newCells.pop_back();
342 }
343
346};
347} // namespace MecaCell
348#endif
CellPlugin< cell_t > embedded_plugin_t
Definition: CellBody.hpp:39
PrimoCell< CellBody > Cell
Definition: Scenario.hpp:16
Where "everything" happens.
Definition: world.hpp:25
void registerPlugins(P &&p, Rest &&... otherPlugins)
Registers a plugin. A plugin is a class or struct that contains hooks.
Definition: world.hpp:169
void registerPlugins()
Definition: world.hpp:174
double getDt() const
Definition: world.hpp:260
void setUpdateBehaviorPeriod(size_t p)
sets the period at which the world must call the updateBehavior method of each cell....
Definition: world.hpp:274
size_t getNbUpdates() const
get the number of update since the creation of the world
Definition: world.hpp:193
void(World *) hook_s
Definition: world.hpp:32
void allForcesHaveBeenAppliedToCells()
this method triggers the allForcesAppliedToCells. It should be called by the embedded physics plugin ...
Definition: world.hpp:244
void setDtInH(double d)
Definition: world.hpp:259
Cell * createCell(Args &&... args)
Creates a new cell and adds it through addCell()
Definition: world.hpp:203
void setDt(double d)
sets the amount by which time is increased at each update() call.
Definition: world.hpp:256
DECLARE_HOOK(onAddCell, beginUpdate, preBehaviorUpdate, preDeleteDeadCellsUpdate, postBehaviorUpdate, endUpdate, allForcesAppliedToCells, destructor) std World(size_t nThreads=0)
cells that are registered to be added
Definition: world.hpp:109
void setShuffleCells(bool s)
Definition: world.hpp:265
double getDtInH() const
Definition: world.hpp:263
void addNewCells()
effectively adds the new cells that were registered by addCell triggers addCell hooks if there is som...
Definition: world.hpp:232
~World()
World's destructor. Triggers the destructor hooks and delete all cells.
Definition: world.hpp:338
void setDtInS(double d)
Definition: world.hpp:257
void update()
main update method
Definition: world.hpp:323
size_t updtBhvPeriod
+1 on cell add. Used for cell's unique ids
Definition: world.hpp:64
Integrator integrator_t
Definition: world.hpp:31
EXPORTABLE(World, KV(frame), KV(cells))
@ignore
void addCell(Cell *c)
adds a cell to the new cells batch (which will be added to the main cells container at the end of the...
Definition: world.hpp:219
void setParallelUpdateBehavior(bool p)
enables or disables the parallelisation of the cells' updateBehavior methods Only has effect if nbThr...
Definition: world.hpp:119
std::vector< std::pair< cell_t *, cell_t * > > getConnectedCellsList()
returns a list of pair of connected cells
Definition: world.hpp:284
double getDtInS() const
Definition: world.hpp:261
vector< Cell * > newCells
Definition: world.hpp:91
bool shuffleCells
Definition: world.hpp:66
size_t nbAddedCells
+1 at each update. cf getNbUpdates()
Definition: world.hpp:63
void setDtInMn(double d)
Definition: world.hpp:258
double getDtInMn() const
Definition: world.hpp:262
double dtH
Definition: world.hpp:86
void setNbThreads(size_t n)
Definition: world.hpp:130
void clearHooks()
end of recursion
Definition: world.hpp:180
void deleteDeadCells()
removes all cells marked dead
Definition: world.hpp:71
double dt
Definition: world.hpp:84
double dtMn
The amount by which time is increased every update.
Definition: world.hpp:85
ThreadPool threadpool
Definition: world.hpp:35
bool parallelUpdateBehavior
period at which the world should call the cells updateBehavior method.
Definition: world.hpp:65
typename embedded_plugin_type< cell_t >::type cellPlugin_t
Definition: world.hpp:58
size_t nbThreads
Definition: world.hpp:27
size_t getUpdateBehaviorPeriod() const
Definition: world.hpp:276
cellPlugin_t cellPlugin
Definition: world.hpp:88
void registerHook(const Hooks &h, hook_t f)
register a single hook method. cf registerPlugins()
Definition: world.hpp:145
size_t frame
Definition: world.hpp:62
size_t getNbThreads()
the size of the threadpool that can be used by plugins to launch asynchronous jobs and also directly ...
Definition: world.hpp:128
void callUpdateBehavior()
calls the updateBehavior of each cell, potentially in parallel (see parallelUpdateBehavior and nbThre...
Definition: world.hpp:299
Represents a cell in the simulation.
Definition: PrimoCell.hpp:53
void setWorld(World *w)
Sets the world for the cell.
Definition: PrimoCell.hpp:154
Simple threadpool, largely inspired by github.com/progschj/ThreadPool.
Definition: threadpool.hpp:24
void setNbThreads(size_t n)
Definition: threadpool.hpp:38
void waitUntilLast()
Definition: threadpool.hpp:59
void autoChunks(Container &v, size_t minChunkSize, double avgTasksPerThread, F f)
Definition: threadpool.hpp:99
A simple vector class template.
Definition: std.hpp:290
void pop_back()
Removes the last element of the vector.
Definition: std.hpp:311
void push_back(const T &value)
Adds an element to the end of the vector.
Definition: std.hpp:304
iterator end()
Returns an iterator to the last element.
Definition: std.hpp:418
T & back()
Returns a reference to the last element.
Definition: std.hpp:338
void insert(iterator position, const T &value)
Inserts an element at the specified position.
Definition: std.hpp:391
bool empty() const
Checks if the vector is empty.
Definition: std.hpp:347
#define KV(p)
Definition: exportable.hpp:30
#define DECLARE_HOOK(...)
Definition: hooktools.hpp:192
this file contains various miscellanious utility functions & helpers *
constexpr size_t eToUI(const T &t)
Definition: utils.hpp:129
ordered_pair< T * > make_ordered_cell_pair(T *a, T *b)
typename make_void< Ts... >::type void_t
Definition: introspect.hpp:12
void shuffle(RandomIt first, RandomIt last)
Shuffles the elements in a range.
Definition: std.hpp:227
static random_engine_t & globalRand()
access to the static global random engine.This pseudo - random generator is* used in random 3D vector...
Definition: config.hpp:30