1
2
3 // DO NOT EDIT !
4 // This file is generated using the MantaFlow preprocessor (prep generate).
5
6 /******************************************************************************
7 *
8 * MantaFlow fluid solver framework
9 * Copyright 2011 Tobias Pfaff, Nils Thuerey
10 *
11 * This program is free software, distributed under the terms of the
12 * Apache License, Version 2.0
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Base class for particle systems
16 *
17 ******************************************************************************/
18
19 #ifndef _PARTICLE_H
20 #define _PARTICLE_H
21
22 #include <vector>
23 #include "grid.h"
24 #include "vectorbase.h"
25 #include "integrator.h"
26 #include "randomstream.h"
27 namespace Manta {
28
29 // fwd decl
30 template<class T> class Grid;
31 class ParticleDataBase;
32 template<class T> class ParticleDataImpl;
33
34 //! Baseclass for particle systems. Does not implement any data
35 class ParticleBase : public PbClass {
36 public:
37 enum SystemType { BASE = 0, PARTICLE, VORTEX, FILAMENT, FLIP, TURBULENCE, INDEX };
38
39 enum ParticleStatus {
40 PNONE = 0,
41 PNEW = (1 << 0), // particles newly created in this step
42 PSPRAY = (1 << 1), // secondary particle types
43 PBUBBLE = (1 << 2),
44 PFOAM = (1 << 3),
45 PTRACER = (1 << 4),
46 PDELETE = (1 << 10), // mark as deleted, will be deleted in next compress() step
47 PINVALID = (1 << 30), // unused
48 };
49
50 ParticleBase(FluidSolver *parent);
_W_0(PyObject * _self,PyObject * _linargs,PyObject * _kwds)51 static int _W_0(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
52 {
53 PbClass *obj = Pb::objFromPy(_self);
54 if (obj)
55 delete obj;
56 try {
57 PbArgs _args(_linargs, _kwds);
58 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
59 pbPreparePlugin(0, "ParticleBase::ParticleBase", !noTiming);
60 {
61 ArgLocker _lock;
62 FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
63 obj = new ParticleBase(parent);
64 obj->registerObject(_self, &_args);
65 _args.check();
66 }
67 pbFinalizePlugin(obj->getParent(), "ParticleBase::ParticleBase", !noTiming);
68 return 0;
69 }
70 catch (std::exception &e) {
71 pbSetError("ParticleBase::ParticleBase", e.what());
72 return -1;
73 }
74 }
75
76 virtual ~ParticleBase();
77
78 //! copy all the particle data thats registered with the other particle system to this one
79 virtual void cloneParticleData(ParticleBase *nm);
80
getType()81 virtual SystemType getType() const
82 {
83 return BASE;
84 }
85 virtual std::string infoString() const;
clone()86 virtual ParticleBase *clone()
87 {
88 assertMsg(false, "Dont use, override...");
89 return NULL;
90 }
91
92 //! slow virtual function to query size, do not use in kernels! use size() instead
getSizeSlow()93 virtual IndexInt getSizeSlow() const
94 {
95 assertMsg(false, "Dont use, override...");
96 return 0;
97 }
98
99 //! add a position as potential candidate for new particle (todo, make usable from parallel
100 //! threads)
101 inline void addBuffered(const Vec3 &pos, int flag = 0);
102
resize(IndexInt size)103 virtual void resize(IndexInt size)
104 {
105 assertMsg(false, "Dont use, override...");
106 return;
107 }
resizeAll(IndexInt size)108 virtual void resizeAll(IndexInt size)
109 {
110 assertMsg(false, "Dont use, override...");
111 return;
112 }
113
114 //! particle data functions
115
116 //! create a particle data object
117 PbClass *create(PbType type, PbTypeVec T = PbTypeVec(), const std::string &name = "");
_W_1(PyObject * _self,PyObject * _linargs,PyObject * _kwds)118 static PyObject *_W_1(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
119 {
120 try {
121 PbArgs _args(_linargs, _kwds);
122 ParticleBase *pbo = dynamic_cast<ParticleBase *>(Pb::objFromPy(_self));
123 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
124 pbPreparePlugin(pbo->getParent(), "ParticleBase::create", !noTiming);
125 PyObject *_retval = 0;
126 {
127 ArgLocker _lock;
128 PbType type = _args.get<PbType>("type", 0, &_lock);
129 PbTypeVec T = _args.getOpt<PbTypeVec>("T", 1, PbTypeVec(), &_lock);
130 const std::string &name = _args.getOpt<std::string>("name", 2, "", &_lock);
131 pbo->_args.copy(_args);
132 _retval = toPy(pbo->create(type, T, name));
133 pbo->_args.check();
134 }
135 pbFinalizePlugin(pbo->getParent(), "ParticleBase::create", !noTiming);
136 return _retval;
137 }
138 catch (std::exception &e) {
139 pbSetError("ParticleBase::create", e.what());
140 return 0;
141 }
142 }
143
144 //! add a particle data field, set its parent particle-system pointer
145 void registerPdata(ParticleDataBase *pdata);
146 void registerPdataReal(ParticleDataImpl<Real> *pdata);
147 void registerPdataVec3(ParticleDataImpl<Vec3> *pdata);
148 void registerPdataInt(ParticleDataImpl<int> *pdata);
149 //! remove a particle data entry
150 void deregister(ParticleDataBase *pdata);
151 //! add one zero entry to all data fields
152 void addAllPdata();
153 // note - deletion of pdata is handled in compress function
154
155 //! how many are there?
getNumPdata()156 IndexInt getNumPdata() const
157 {
158 return mPartData.size();
159 }
160 //! access one of the fields
getPdata(int i)161 ParticleDataBase *getPdata(int i)
162 {
163 return mPartData[i];
164 }
165
166 //! expose maximum number of particles to python
167 int mMaxParticles;
_GET_mMaxParticles(PyObject * self,void * cl)168 static PyObject *_GET_mMaxParticles(PyObject *self, void *cl)
169 {
170 ParticleBase *pbo = dynamic_cast<ParticleBase *>(Pb::objFromPy(self));
171 return toPy(pbo->mMaxParticles);
172 }
_SET_mMaxParticles(PyObject * self,PyObject * val,void * cl)173 static int _SET_mMaxParticles(PyObject *self, PyObject *val, void *cl)
174 {
175 ParticleBase *pbo = dynamic_cast<ParticleBase *>(Pb::objFromPy(self));
176 pbo->mMaxParticles = fromPy<int>(val);
177 return 0;
178 }
179
180 protected:
181 //! new particle candidates
182 std::vector<Vec3> mNewBufferPos;
183 std::vector<int> mNewBufferFlag;
184
185 //! allow automatic compression / resize? disallowed for, eg, flip particle systems
186 bool mAllowCompress;
187
188 //! store particle data , each pointer has its own storage vector of a certain type (int, real,
189 //! vec3)
190 std::vector<ParticleDataBase *> mPartData;
191 //! lists of different types, for fast operations w/o virtual function calls (all calls necessary
192 //! per particle)
193 std::vector<ParticleDataImpl<Real> *> mPdataReal;
194 std::vector<ParticleDataImpl<Vec3> *> mPdataVec3;
195 std::vector<ParticleDataImpl<int> *>
196 mPdataInt; //! indicate that pdata of this particle system is copied, and needs to be freed
197 bool mFreePdata;
198 public:
199 PbArgs _args;
200 }
201 #define _C_ParticleBase
202 ;
203
204 //! Main class for particle systems
205 /*! Basetype S must at least contain flag, pos fields */
206 template<class S> class ParticleSystem : public ParticleBase {
207 public:
ParticleSystem(FluidSolver * parent)208 ParticleSystem(FluidSolver *parent) : ParticleBase(parent), mDeletes(0), mDeleteChunk(0)
209 {
210 }
_W_2(PyObject * _self,PyObject * _linargs,PyObject * _kwds)211 static int _W_2(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
212 {
213 PbClass *obj = Pb::objFromPy(_self);
214 if (obj)
215 delete obj;
216 try {
217 PbArgs _args(_linargs, _kwds);
218 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
219 pbPreparePlugin(0, "ParticleSystem::ParticleSystem", !noTiming);
220 {
221 ArgLocker _lock;
222 FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
223 obj = new ParticleSystem(parent);
224 obj->registerObject(_self, &_args);
225 _args.check();
226 }
227 pbFinalizePlugin(obj->getParent(), "ParticleSystem::ParticleSystem", !noTiming);
228 return 0;
229 }
230 catch (std::exception &e) {
231 pbSetError("ParticleSystem::ParticleSystem", e.what());
232 return -1;
233 }
234 }
235
~ParticleSystem()236 virtual ~ParticleSystem(){};
237
getType()238 virtual SystemType getType() const
239 {
240 return S::getType();
241 };
242
243 //! accessors
244 inline S &operator[](IndexInt idx)
245 {
246 DEBUG_ONLY(checkPartIndex(idx));
247 return mData[idx];
248 }
249 inline const S &operator[](IndexInt idx) const
250 {
251 DEBUG_ONLY(checkPartIndex(idx));
252 return mData[idx];
253 }
254 //! return size of container
255 //! note , python binding disabled for now! cannot yet deal with long-long types
size()256 inline IndexInt size() const
257 {
258 return mData.size();
259 }
260 //! slow virtual function of base class, also returns size
getSizeSlow()261 virtual IndexInt getSizeSlow() const
262 {
263 return size();
264 }
265 //! note , special call for python, note - doesnt support more than 2b parts!
pySize()266 int pySize() const
267 {
268 return (int)mData.size();
269 }
_W_3(PyObject * _self,PyObject * _linargs,PyObject * _kwds)270 static PyObject *_W_3(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
271 {
272 try {
273 PbArgs _args(_linargs, _kwds);
274 ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
275 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
276 pbPreparePlugin(pbo->getParent(), "ParticleSystem::pySize", !noTiming);
277 PyObject *_retval = 0;
278 {
279 ArgLocker _lock;
280 pbo->_args.copy(_args);
281 _retval = toPy(pbo->pySize());
282 pbo->_args.check();
283 }
284 pbFinalizePlugin(pbo->getParent(), "ParticleSystem::pySize", !noTiming);
285 return _retval;
286 }
287 catch (std::exception &e) {
288 pbSetError("ParticleSystem::pySize", e.what());
289 return 0;
290 }
291 }
292
293 //! query status
getStatus(IndexInt idx)294 inline int getStatus(IndexInt idx) const
295 {
296 DEBUG_ONLY(checkPartIndex(idx));
297 return mData[idx].flag;
298 }
isActive(IndexInt idx)299 inline bool isActive(IndexInt idx) const
300 {
301 DEBUG_ONLY(checkPartIndex(idx));
302 return (mData[idx].flag & PDELETE) == 0;
303 }
isSpray(IndexInt idx)304 inline bool isSpray(IndexInt idx) const
305 {
306 DEBUG_ONLY(checkPartIndex(idx));
307 return (mData[idx].flag & PSPRAY);
308 }
isBubble(IndexInt idx)309 inline bool isBubble(IndexInt idx) const
310 {
311 DEBUG_ONLY(checkPartIndex(idx));
312 return (mData[idx].flag & PBUBBLE);
313 }
isFoam(IndexInt idx)314 inline bool isFoam(IndexInt idx) const
315 {
316 DEBUG_ONLY(checkPartIndex(idx));
317 return (mData[idx].flag & PFOAM);
318 }
isTracer(IndexInt idx)319 inline bool isTracer(IndexInt idx) const
320 {
321 DEBUG_ONLY(checkPartIndex(idx));
322 return (mData[idx].flag & PTRACER);
323 }
324
325 //! update status
setStatus(IndexInt idx,const int status)326 inline void setStatus(IndexInt idx, const int status)
327 {
328 DEBUG_ONLY(checkPartIndex(idx));
329 mData[idx].flag = status;
330 }
331
332 //! safe accessor for python
setPos(const IndexInt idx,const Vec3 & pos)333 void setPos(const IndexInt idx, const Vec3 &pos)
334 {
335 DEBUG_ONLY(checkPartIndex(idx));
336 mData[idx].pos = pos;
337 }
_W_4(PyObject * _self,PyObject * _linargs,PyObject * _kwds)338 static PyObject *_W_4(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
339 {
340 try {
341 PbArgs _args(_linargs, _kwds);
342 ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
343 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
344 pbPreparePlugin(pbo->getParent(), "ParticleSystem::setPos", !noTiming);
345 PyObject *_retval = 0;
346 {
347 ArgLocker _lock;
348 const IndexInt idx = _args.get<IndexInt>("idx", 0, &_lock);
349 const Vec3 &pos = _args.get<Vec3>("pos", 1, &_lock);
350 pbo->_args.copy(_args);
351 _retval = getPyNone();
352 pbo->setPos(idx, pos);
353 pbo->_args.check();
354 }
355 pbFinalizePlugin(pbo->getParent(), "ParticleSystem::setPos", !noTiming);
356 return _retval;
357 }
358 catch (std::exception &e) {
359 pbSetError("ParticleSystem::setPos", e.what());
360 return 0;
361 }
362 }
363
getPos(const IndexInt idx)364 const Vec3 &getPos(const IndexInt idx) const
365 {
366 DEBUG_ONLY(checkPartIndex(idx));
367 return mData[idx].pos;
368 }
_W_5(PyObject * _self,PyObject * _linargs,PyObject * _kwds)369 static PyObject *_W_5(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
370 {
371 try {
372 PbArgs _args(_linargs, _kwds);
373 ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
374 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
375 pbPreparePlugin(pbo->getParent(), "ParticleSystem::getPos", !noTiming);
376 PyObject *_retval = 0;
377 {
378 ArgLocker _lock;
379 const IndexInt idx = _args.get<IndexInt>("idx", 0, &_lock);
380 pbo->_args.copy(_args);
381 _retval = toPy(pbo->getPos(idx));
382 pbo->_args.check();
383 }
384 pbFinalizePlugin(pbo->getParent(), "ParticleSystem::getPos", !noTiming);
385 return _retval;
386 }
387 catch (std::exception &e) {
388 pbSetError("ParticleSystem::getPos", e.what());
389 return 0;
390 }
391 }
392
393 //! copy all positions into pdata vec3 field
394 void getPosPdata(ParticleDataImpl<Vec3> &target) const;
_W_6(PyObject * _self,PyObject * _linargs,PyObject * _kwds)395 static PyObject *_W_6(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
396 {
397 try {
398 PbArgs _args(_linargs, _kwds);
399 ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
400 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
401 pbPreparePlugin(pbo->getParent(), "ParticleSystem::getPosPdata", !noTiming);
402 PyObject *_retval = 0;
403 {
404 ArgLocker _lock;
405 ParticleDataImpl<Vec3> &target = *_args.getPtr<ParticleDataImpl<Vec3>>(
406 "target", 0, &_lock);
407 pbo->_args.copy(_args);
408 _retval = getPyNone();
409 pbo->getPosPdata(target);
410 pbo->_args.check();
411 }
412 pbFinalizePlugin(pbo->getParent(), "ParticleSystem::getPosPdata", !noTiming);
413 return _retval;
414 }
415 catch (std::exception &e) {
416 pbSetError("ParticleSystem::getPosPdata", e.what());
417 return 0;
418 }
419 }
420
421 void setPosPdata(const ParticleDataImpl<Vec3> &source);
_W_7(PyObject * _self,PyObject * _linargs,PyObject * _kwds)422 static PyObject *_W_7(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
423 {
424 try {
425 PbArgs _args(_linargs, _kwds);
426 ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
427 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
428 pbPreparePlugin(pbo->getParent(), "ParticleSystem::setPosPdata", !noTiming);
429 PyObject *_retval = 0;
430 {
431 ArgLocker _lock;
432 const ParticleDataImpl<Vec3> &source = *_args.getPtr<ParticleDataImpl<Vec3>>(
433 "source", 0, &_lock);
434 pbo->_args.copy(_args);
435 _retval = getPyNone();
436 pbo->setPosPdata(source);
437 pbo->_args.check();
438 }
439 pbFinalizePlugin(pbo->getParent(), "ParticleSystem::setPosPdata", !noTiming);
440 return _retval;
441 }
442 catch (std::exception &e) {
443 pbSetError("ParticleSystem::setPosPdata", e.what());
444 return 0;
445 }
446 }
447
448 //! transform coordinate system from one grid size to another (usually upon load)
449 void transformPositions(Vec3i dimOld, Vec3i dimNew);
450
451 //! explicitly trigger compression from outside
doCompress()452 void doCompress()
453 {
454 if (mDeletes > mDeleteChunk)
455 compress();
456 }
457 //! insert buffered positions as new particles, update additional particle data
458 void insertBufferedParticles();
459 //! resize only the data vector, only use if you know what you're doing, otherwise use
460 //! resizeAll()
resize(IndexInt size)461 virtual void resize(IndexInt size)
462 {
463 mData.resize(size);
464 }
465 //! resize data vector, and all pdata fields
466 virtual void resizeAll(IndexInt size);
467
468 //! adding and deleting
469 inline void kill(IndexInt idx);
470 IndexInt add(const S &data);
471 //! remove all particles, init 0 length arrays (also pdata)
472 void clear();
_W_8(PyObject * _self,PyObject * _linargs,PyObject * _kwds)473 static PyObject *_W_8(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
474 {
475 try {
476 PbArgs _args(_linargs, _kwds);
477 ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
478 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
479 pbPreparePlugin(pbo->getParent(), "ParticleSystem::clear", !noTiming);
480 PyObject *_retval = 0;
481 {
482 ArgLocker _lock;
483 pbo->_args.copy(_args);
484 _retval = getPyNone();
485 pbo->clear();
486 pbo->_args.check();
487 }
488 pbFinalizePlugin(pbo->getParent(), "ParticleSystem::clear", !noTiming);
489 return _retval;
490 }
491 catch (std::exception &e) {
492 pbSetError("ParticleSystem::clear", e.what());
493 return 0;
494 }
495 }
496
497 //! Advect particle in grid velocity field
498 void advectInGrid(const FlagGrid &flags,
499 const MACGrid &vel,
500 const int integrationMode,
501 const bool deleteInObstacle = true,
502 const bool stopInObstacle = true,
503 const bool skipNew = false,
504 const ParticleDataImpl<int> *ptype = NULL,
505 const int exclude = 0);
_W_9(PyObject * _self,PyObject * _linargs,PyObject * _kwds)506 static PyObject *_W_9(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
507 {
508 try {
509 PbArgs _args(_linargs, _kwds);
510 ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
511 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
512 pbPreparePlugin(pbo->getParent(), "ParticleSystem::advectInGrid", !noTiming);
513 PyObject *_retval = 0;
514 {
515 ArgLocker _lock;
516 const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
517 const MACGrid &vel = *_args.getPtr<MACGrid>("vel", 1, &_lock);
518 const int integrationMode = _args.get<int>("integrationMode", 2, &_lock);
519 const bool deleteInObstacle = _args.getOpt<bool>("deleteInObstacle", 3, true, &_lock);
520 const bool stopInObstacle = _args.getOpt<bool>("stopInObstacle", 4, true, &_lock);
521 const bool skipNew = _args.getOpt<bool>("skipNew", 5, false, &_lock);
522 const ParticleDataImpl<int> *ptype = _args.getPtrOpt<ParticleDataImpl<int>>(
523 "ptype", 6, NULL, &_lock);
524 const int exclude = _args.getOpt<int>("exclude", 7, 0, &_lock);
525 pbo->_args.copy(_args);
526 _retval = getPyNone();
527 pbo->advectInGrid(flags,
528 vel,
529 integrationMode,
530 deleteInObstacle,
531 stopInObstacle,
532 skipNew,
533 ptype,
534 exclude);
535 pbo->_args.check();
536 }
537 pbFinalizePlugin(pbo->getParent(), "ParticleSystem::advectInGrid", !noTiming);
538 return _retval;
539 }
540 catch (std::exception &e) {
541 pbSetError("ParticleSystem::advectInGrid", e.what());
542 return 0;
543 }
544 }
545
546 //! Project particles outside obstacles
547 void projectOutside(Grid<Vec3> &gradient);
_W_10(PyObject * _self,PyObject * _linargs,PyObject * _kwds)548 static PyObject *_W_10(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
549 {
550 try {
551 PbArgs _args(_linargs, _kwds);
552 ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
553 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
554 pbPreparePlugin(pbo->getParent(), "ParticleSystem::projectOutside", !noTiming);
555 PyObject *_retval = 0;
556 {
557 ArgLocker _lock;
558 Grid<Vec3> &gradient = *_args.getPtr<Grid<Vec3>>("gradient", 0, &_lock);
559 pbo->_args.copy(_args);
560 _retval = getPyNone();
561 pbo->projectOutside(gradient);
562 pbo->_args.check();
563 }
564 pbFinalizePlugin(pbo->getParent(), "ParticleSystem::projectOutside", !noTiming);
565 return _retval;
566 }
567 catch (std::exception &e) {
568 pbSetError("ParticleSystem::projectOutside", e.what());
569 return 0;
570 }
571 }
572
573 void projectOutOfBnd(const FlagGrid &flags,
574 const Real bnd,
575 const std::string &plane = "xXyYzZ",
576 const ParticleDataImpl<int> *ptype = NULL,
577 const int exclude = 0);
_W_11(PyObject * _self,PyObject * _linargs,PyObject * _kwds)578 static PyObject *_W_11(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
579 {
580 try {
581 PbArgs _args(_linargs, _kwds);
582 ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
583 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
584 pbPreparePlugin(pbo->getParent(), "ParticleSystem::projectOutOfBnd", !noTiming);
585 PyObject *_retval = 0;
586 {
587 ArgLocker _lock;
588 const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
589 const Real bnd = _args.get<Real>("bnd", 1, &_lock);
590 const std::string &plane = _args.getOpt<std::string>("plane", 2, "xXyYzZ", &_lock);
591 const ParticleDataImpl<int> *ptype = _args.getPtrOpt<ParticleDataImpl<int>>(
592 "ptype", 3, NULL, &_lock);
593 const int exclude = _args.getOpt<int>("exclude", 4, 0, &_lock);
594 pbo->_args.copy(_args);
595 _retval = getPyNone();
596 pbo->projectOutOfBnd(flags, bnd, plane, ptype, exclude);
597 pbo->_args.check();
598 }
599 pbFinalizePlugin(pbo->getParent(), "ParticleSystem::projectOutOfBnd", !noTiming);
600 return _retval;
601 }
602 catch (std::exception &e) {
603 pbSetError("ParticleSystem::projectOutOfBnd", e.what());
604 return 0;
605 }
606 }
607
608 virtual ParticleBase *clone();
609 virtual std::string infoString() const;
610
611 //! debugging
612 inline void checkPartIndex(IndexInt idx) const;
613
614 protected:
615 //! deletion count , and interval for re-compressing
616 IndexInt mDeletes, mDeleteChunk;
617 //! the particle data
618 std::vector<S> mData;
619 //! reduce storage , called by doCompress
620 virtual void compress();
621 public:
622 PbArgs _args;
623 }
624 #define _C_ParticleSystem
625 ;
626
627 //******************************************************************************
628
629 //! Simplest data class for particle systems
630 //! contains a position and an int flag; note that these are deprectated, and will at
631 //! some point be replaced by the more flexible pdata fields. For now manually copy with
632 //! getPosPdata / setPosPdata.
633 struct BasicParticleData {
634 public:
BasicParticleDataBasicParticleData635 BasicParticleData() : pos(0.), flag(0)
636 {
637 }
BasicParticleDataBasicParticleData638 BasicParticleData(const Vec3 &p) : pos(p), flag(0)
639 {
640 }
getTypeBasicParticleData641 static ParticleBase::SystemType getType()
642 {
643 return ParticleBase::PARTICLE;
644 }
645
646 //! data (note, this size is currently hard coded for uni i/o)
647 Vec3 pos;
648 int flag;
649 };
650
651 class BasicParticleSystem : public ParticleSystem<BasicParticleData> {
652 public:
653 BasicParticleSystem(FluidSolver *parent);
_W_12(PyObject * _self,PyObject * _linargs,PyObject * _kwds)654 static int _W_12(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
655 {
656 PbClass *obj = Pb::objFromPy(_self);
657 if (obj)
658 delete obj;
659 try {
660 PbArgs _args(_linargs, _kwds);
661 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
662 pbPreparePlugin(0, "BasicParticleSystem::BasicParticleSystem", !noTiming);
663 {
664 ArgLocker _lock;
665 FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
666 obj = new BasicParticleSystem(parent);
667 obj->registerObject(_self, &_args);
668 _args.check();
669 }
670 pbFinalizePlugin(obj->getParent(), "BasicParticleSystem::BasicParticleSystem", !noTiming);
671 return 0;
672 }
673 catch (std::exception &e) {
674 pbSetError("BasicParticleSystem::BasicParticleSystem", e.what());
675 return -1;
676 }
677 }
678
679 //! file io
680 int save(const std::string name);
_W_13(PyObject * _self,PyObject * _linargs,PyObject * _kwds)681 static PyObject *_W_13(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
682 {
683 try {
684 PbArgs _args(_linargs, _kwds);
685 BasicParticleSystem *pbo = dynamic_cast<BasicParticleSystem *>(Pb::objFromPy(_self));
686 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
687 pbPreparePlugin(pbo->getParent(), "BasicParticleSystem::save", !noTiming);
688 PyObject *_retval = 0;
689 {
690 ArgLocker _lock;
691 const std::string name = _args.get<std::string>("name", 0, &_lock);
692 pbo->_args.copy(_args);
693 _retval = toPy(pbo->save(name));
694 pbo->_args.check();
695 }
696 pbFinalizePlugin(pbo->getParent(), "BasicParticleSystem::save", !noTiming);
697 return _retval;
698 }
699 catch (std::exception &e) {
700 pbSetError("BasicParticleSystem::save", e.what());
701 return 0;
702 }
703 }
704
705 int load(const std::string name);
_W_14(PyObject * _self,PyObject * _linargs,PyObject * _kwds)706 static PyObject *_W_14(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
707 {
708 try {
709 PbArgs _args(_linargs, _kwds);
710 BasicParticleSystem *pbo = dynamic_cast<BasicParticleSystem *>(Pb::objFromPy(_self));
711 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
712 pbPreparePlugin(pbo->getParent(), "BasicParticleSystem::load", !noTiming);
713 PyObject *_retval = 0;
714 {
715 ArgLocker _lock;
716 const std::string name = _args.get<std::string>("name", 0, &_lock);
717 pbo->_args.copy(_args);
718 _retval = toPy(pbo->load(name));
719 pbo->_args.check();
720 }
721 pbFinalizePlugin(pbo->getParent(), "BasicParticleSystem::load", !noTiming);
722 return _retval;
723 }
724 catch (std::exception &e) {
725 pbSetError("BasicParticleSystem::load", e.what());
726 return 0;
727 }
728 }
729
730 //! save to text file
731 void writeParticlesText(const std::string name) const;
732 //! other output formats
733 void writeParticlesRawPositionsGz(const std::string name) const;
734 void writeParticlesRawVelocityGz(const std::string name) const;
735
736 //! read from other particle system (with resize)
737 void readParticles(BasicParticleSystem *from);
_W_15(PyObject * _self,PyObject * _linargs,PyObject * _kwds)738 static PyObject *_W_15(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
739 {
740 try {
741 PbArgs _args(_linargs, _kwds);
742 BasicParticleSystem *pbo = dynamic_cast<BasicParticleSystem *>(Pb::objFromPy(_self));
743 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
744 pbPreparePlugin(pbo->getParent(), "BasicParticleSystem::readParticles", !noTiming);
745 PyObject *_retval = 0;
746 {
747 ArgLocker _lock;
748 BasicParticleSystem *from = _args.getPtr<BasicParticleSystem>("from", 0, &_lock);
749 pbo->_args.copy(_args);
750 _retval = getPyNone();
751 pbo->readParticles(from);
752 pbo->_args.check();
753 }
754 pbFinalizePlugin(pbo->getParent(), "BasicParticleSystem::readParticles", !noTiming);
755 return _retval;
756 }
757 catch (std::exception &e) {
758 pbSetError("BasicParticleSystem::readParticles", e.what());
759 return 0;
760 }
761 }
762
763 //! add particles in python
addParticle(Vec3 pos)764 void addParticle(Vec3 pos)
765 {
766 add(BasicParticleData(pos));
767 }
_W_16(PyObject * _self,PyObject * _linargs,PyObject * _kwds)768 static PyObject *_W_16(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
769 {
770 try {
771 PbArgs _args(_linargs, _kwds);
772 BasicParticleSystem *pbo = dynamic_cast<BasicParticleSystem *>(Pb::objFromPy(_self));
773 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
774 pbPreparePlugin(pbo->getParent(), "BasicParticleSystem::addParticle", !noTiming);
775 PyObject *_retval = 0;
776 {
777 ArgLocker _lock;
778 Vec3 pos = _args.get<Vec3>("pos", 0, &_lock);
779 pbo->_args.copy(_args);
780 _retval = getPyNone();
781 pbo->addParticle(pos);
782 pbo->_args.check();
783 }
784 pbFinalizePlugin(pbo->getParent(), "BasicParticleSystem::addParticle", !noTiming);
785 return _retval;
786 }
787 catch (std::exception &e) {
788 pbSetError("BasicParticleSystem::addParticle", e.what());
789 return 0;
790 }
791 }
792
793 //! dangerous, get low level access - avoid usage, only used in vortex filament advection for now
getData()794 std::vector<BasicParticleData> &getData()
795 {
796 return mData;
797 }
798
799 void printParts(IndexInt start = -1, IndexInt stop = -1, bool printIndex = false);
_W_17(PyObject * _self,PyObject * _linargs,PyObject * _kwds)800 static PyObject *_W_17(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
801 {
802 try {
803 PbArgs _args(_linargs, _kwds);
804 BasicParticleSystem *pbo = dynamic_cast<BasicParticleSystem *>(Pb::objFromPy(_self));
805 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
806 pbPreparePlugin(pbo->getParent(), "BasicParticleSystem::printParts", !noTiming);
807 PyObject *_retval = 0;
808 {
809 ArgLocker _lock;
810 IndexInt start = _args.getOpt<IndexInt>("start", 0, -1, &_lock);
811 IndexInt stop = _args.getOpt<IndexInt>("stop", 1, -1, &_lock);
812 bool printIndex = _args.getOpt<bool>("printIndex", 2, false, &_lock);
813 pbo->_args.copy(_args);
814 _retval = getPyNone();
815 pbo->printParts(start, stop, printIndex);
816 pbo->_args.check();
817 }
818 pbFinalizePlugin(pbo->getParent(), "BasicParticleSystem::printParts", !noTiming);
819 return _retval;
820 }
821 catch (std::exception &e) {
822 pbSetError("BasicParticleSystem::printParts", e.what());
823 return 0;
824 }
825 }
826
827 //! get data pointer of particle data
828 std::string getDataPointer();
_W_18(PyObject * _self,PyObject * _linargs,PyObject * _kwds)829 static PyObject *_W_18(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
830 {
831 try {
832 PbArgs _args(_linargs, _kwds);
833 BasicParticleSystem *pbo = dynamic_cast<BasicParticleSystem *>(Pb::objFromPy(_self));
834 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
835 pbPreparePlugin(pbo->getParent(), "BasicParticleSystem::getDataPointer", !noTiming);
836 PyObject *_retval = 0;
837 {
838 ArgLocker _lock;
839 pbo->_args.copy(_args);
840 _retval = toPy(pbo->getDataPointer());
841 pbo->_args.check();
842 }
843 pbFinalizePlugin(pbo->getParent(), "BasicParticleSystem::getDataPointer", !noTiming);
844 return _retval;
845 }
846 catch (std::exception &e) {
847 pbSetError("BasicParticleSystem::getDataPointer", e.what());
848 return 0;
849 }
850 }
851
852 public:
853 PbArgs _args;
854 }
855 #define _C_BasicParticleSystem
856 ;
857
858 //******************************************************************************
859
860 //! Index into other particle system
861 // used for grid based neighborhood searches on generic particle systems (stores
862 // only active particles, and reduces copied data)
863 // note - pos & flag are disabled here, do not use!
864 struct ParticleIndexData {
865 public:
ParticleIndexDataParticleIndexData866 ParticleIndexData() : sourceIndex(0)
867 {
868 }
getTypeParticleIndexData869 static ParticleBase::SystemType getType()
870 {
871 return ParticleBase::INDEX;
872 }
873
874 IndexInt sourceIndex; // index of this particle in the original particle system
875 //! note - the following two are needed for template instantiation, but not used
876 //! for the particle index system (use values from original one!)
877 static Vec3 pos; // do not use...
878 static int flag; // not needed usally
879 // Vec3 pos; // enable for debugging
880 };
881
882 class ParticleIndexSystem : public ParticleSystem<ParticleIndexData> {
883 public:
ParticleIndexSystem(FluidSolver * parent)884 ParticleIndexSystem(FluidSolver *parent) : ParticleSystem<ParticleIndexData>(parent)
885 {
886 }
_W_19(PyObject * _self,PyObject * _linargs,PyObject * _kwds)887 static int _W_19(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
888 {
889 PbClass *obj = Pb::objFromPy(_self);
890 if (obj)
891 delete obj;
892 try {
893 PbArgs _args(_linargs, _kwds);
894 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
895 pbPreparePlugin(0, "ParticleIndexSystem::ParticleIndexSystem", !noTiming);
896 {
897 ArgLocker _lock;
898 FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
899 obj = new ParticleIndexSystem(parent);
900 obj->registerObject(_self, &_args);
901 _args.check();
902 }
903 pbFinalizePlugin(obj->getParent(), "ParticleIndexSystem::ParticleIndexSystem", !noTiming);
904 return 0;
905 }
906 catch (std::exception &e) {
907 pbSetError("ParticleIndexSystem::ParticleIndexSystem", e.what());
908 return -1;
909 }
910 };
911 public:
912 PbArgs _args;
913 }
914 #define _C_ParticleIndexSystem
915 ;
916
917 //******************************************************************************
918
919 //! Particle set with connectivity
920
921 template<class DATA, class CON> class ConnectedParticleSystem : public ParticleSystem<DATA> {
922 public:
ConnectedParticleSystem(FluidSolver * parent)923 ConnectedParticleSystem(FluidSolver *parent) : ParticleSystem<DATA>(parent)
924 {
925 }
_W_20(PyObject * _self,PyObject * _linargs,PyObject * _kwds)926 static int _W_20(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
927 {
928 PbClass *obj = Pb::objFromPy(_self);
929 if (obj)
930 delete obj;
931 try {
932 PbArgs _args(_linargs, _kwds);
933 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
934 pbPreparePlugin(0, "ConnectedParticleSystem::ConnectedParticleSystem", !noTiming);
935 {
936 ArgLocker _lock;
937 FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
938 obj = new ConnectedParticleSystem(parent);
939 obj->registerObject(_self, &_args);
940 _args.check();
941 }
942 pbFinalizePlugin(
943 obj->getParent(), "ConnectedParticleSystem::ConnectedParticleSystem", !noTiming);
944 return 0;
945 }
946 catch (std::exception &e) {
947 pbSetError("ConnectedParticleSystem::ConnectedParticleSystem", e.what());
948 return -1;
949 }
950 }
951
952 //! accessors
isSegActive(int i)953 inline bool isSegActive(int i)
954 {
955 return (mSegments[i].flag & ParticleBase::PDELETE) == 0;
956 }
segSize()957 inline int segSize() const
958 {
959 return mSegments.size();
960 }
seg(int i)961 inline CON &seg(int i)
962 {
963 return mSegments[i];
964 }
seg(int i)965 inline const CON &seg(int i) const
966 {
967 return mSegments[i];
968 }
969
970 virtual ParticleBase *clone();
971
972 protected:
973 std::vector<CON> mSegments;
974 virtual void compress();
975 public:
976 PbArgs _args;
977 }
978 #define _C_ConnectedParticleSystem
979 ;
980
981 //******************************************************************************
982
983 //! abstract interface for particle data
984 class ParticleDataBase : public PbClass {
985 public:
986 ParticleDataBase(FluidSolver *parent);
_W_21(PyObject * _self,PyObject * _linargs,PyObject * _kwds)987 static int _W_21(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
988 {
989 PbClass *obj = Pb::objFromPy(_self);
990 if (obj)
991 delete obj;
992 try {
993 PbArgs _args(_linargs, _kwds);
994 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
995 pbPreparePlugin(0, "ParticleDataBase::ParticleDataBase", !noTiming);
996 {
997 ArgLocker _lock;
998 FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
999 obj = new ParticleDataBase(parent);
1000 obj->registerObject(_self, &_args);
1001 _args.check();
1002 }
1003 pbFinalizePlugin(obj->getParent(), "ParticleDataBase::ParticleDataBase", !noTiming);
1004 return 0;
1005 }
1006 catch (std::exception &e) {
1007 pbSetError("ParticleDataBase::ParticleDataBase", e.what());
1008 return -1;
1009 }
1010 }
1011
1012 virtual ~ParticleDataBase();
1013
1014 //! data type IDs, in line with those for grids
1015 enum PdataType { TypeNone = 0, TypeReal = 1, TypeInt = 2, TypeVec3 = 4 };
1016
1017 //! interface functions, using assert instead of pure virtual for python compatibility
getSizeSlow()1018 virtual IndexInt getSizeSlow() const
1019 {
1020 assertMsg(false, "Dont use, override...");
1021 return 0;
1022 }
addEntry()1023 virtual void addEntry()
1024 {
1025 assertMsg(false, "Dont use, override...");
1026 return;
1027 }
clone()1028 virtual ParticleDataBase *clone()
1029 {
1030 assertMsg(false, "Dont use, override...");
1031 return NULL;
1032 }
getType()1033 virtual PdataType getType() const
1034 {
1035 assertMsg(false, "Dont use, override...");
1036 return TypeNone;
1037 }
resize(IndexInt size)1038 virtual void resize(IndexInt size)
1039 {
1040 assertMsg(false, "Dont use, override...");
1041 return;
1042 }
copyValueSlow(IndexInt from,IndexInt to)1043 virtual void copyValueSlow(IndexInt from, IndexInt to)
1044 {
1045 assertMsg(false, "Dont use, override...");
1046 return;
1047 }
1048
1049 //! set / get base pointer to parent particle system
setParticleSys(ParticleBase * set)1050 void setParticleSys(ParticleBase *set)
1051 {
1052 mpParticleSys = set;
1053 }
getParticleSys()1054 ParticleBase *getParticleSys()
1055 {
1056 return mpParticleSys;
1057 }
1058
1059 //! debugging
1060 inline void checkPartIndex(IndexInt idx) const;
1061
1062 protected:
1063 ParticleBase *mpParticleSys;
1064 public:
1065 PbArgs _args;
1066 }
1067 #define _C_ParticleDataBase
1068 ;
1069
1070 //! abstract interface for particle data
1071
1072 template<class T> class ParticleDataImpl : public ParticleDataBase {
1073 public:
1074 ParticleDataImpl(FluidSolver *parent);
_W_22(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1075 static int _W_22(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1076 {
1077 PbClass *obj = Pb::objFromPy(_self);
1078 if (obj)
1079 delete obj;
1080 try {
1081 PbArgs _args(_linargs, _kwds);
1082 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1083 pbPreparePlugin(0, "ParticleDataImpl::ParticleDataImpl", !noTiming);
1084 {
1085 ArgLocker _lock;
1086 FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
1087 obj = new ParticleDataImpl(parent);
1088 obj->registerObject(_self, &_args);
1089 _args.check();
1090 }
1091 pbFinalizePlugin(obj->getParent(), "ParticleDataImpl::ParticleDataImpl", !noTiming);
1092 return 0;
1093 }
1094 catch (std::exception &e) {
1095 pbSetError("ParticleDataImpl::ParticleDataImpl", e.what());
1096 return -1;
1097 }
1098 }
1099
1100 ParticleDataImpl(FluidSolver *parent, ParticleDataImpl<T> *other);
1101 virtual ~ParticleDataImpl();
1102
1103 //! access data
get(const IndexInt idx)1104 inline T &get(const IndexInt idx)
1105 {
1106 DEBUG_ONLY(checkPartIndex(idx));
1107 return mData[idx];
1108 }
get(const IndexInt idx)1109 inline const T &get(const IndexInt idx) const
1110 {
1111 DEBUG_ONLY(checkPartIndex(idx));
1112 return mData[idx];
1113 }
1114 inline T &operator[](const IndexInt idx)
1115 {
1116 DEBUG_ONLY(checkPartIndex(idx));
1117 return mData[idx];
1118 }
1119 inline const T &operator[](const IndexInt idx) const
1120 {
1121 DEBUG_ONLY(checkPartIndex(idx));
1122 return mData[idx];
1123 }
1124
1125 //! set data
set(const IndexInt idx,T & val)1126 inline void set(const IndexInt idx, T &val)
1127 {
1128 DEBUG_ONLY(checkPartIndex(idx));
1129 mData[idx] = val;
1130 }
1131
1132 //! set all values to 0, note - different from particleSystem::clear! doesnt modify size of array
1133 //! (has to stay in sync with parent system)
1134 void clear();
_W_23(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1135 static PyObject *_W_23(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1136 {
1137 try {
1138 PbArgs _args(_linargs, _kwds);
1139 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1140 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1141 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::clear", !noTiming);
1142 PyObject *_retval = 0;
1143 {
1144 ArgLocker _lock;
1145 pbo->_args.copy(_args);
1146 _retval = getPyNone();
1147 pbo->clear();
1148 pbo->_args.check();
1149 }
1150 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::clear", !noTiming);
1151 return _retval;
1152 }
1153 catch (std::exception &e) {
1154 pbSetError("ParticleDataImpl::clear", e.what());
1155 return 0;
1156 }
1157 }
1158
1159 //! set grid from which to get data...
1160 void setSource(Grid<T> *grid, bool isMAC = false);
_W_24(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1161 static PyObject *_W_24(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1162 {
1163 try {
1164 PbArgs _args(_linargs, _kwds);
1165 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1166 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1167 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::setSource", !noTiming);
1168 PyObject *_retval = 0;
1169 {
1170 ArgLocker _lock;
1171 Grid<T> *grid = _args.getPtr<Grid<T>>("grid", 0, &_lock);
1172 bool isMAC = _args.getOpt<bool>("isMAC", 1, false, &_lock);
1173 pbo->_args.copy(_args);
1174 _retval = getPyNone();
1175 pbo->setSource(grid, isMAC);
1176 pbo->_args.check();
1177 }
1178 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::setSource", !noTiming);
1179 return _retval;
1180 }
1181 catch (std::exception &e) {
1182 pbSetError("ParticleDataImpl::setSource", e.what());
1183 return 0;
1184 }
1185 }
1186
1187 //! particle data base interface
1188 virtual IndexInt getSizeSlow() const;
1189 virtual void addEntry();
1190 virtual ParticleDataBase *clone();
1191 virtual PdataType getType() const;
1192 virtual void resize(IndexInt s);
1193 virtual void copyValueSlow(IndexInt from, IndexInt to);
1194
size()1195 IndexInt size() const
1196 {
1197 return mData.size();
1198 }
1199
1200 //! fast inlined functions for per particle operations
copyValue(IndexInt from,IndexInt to)1201 inline void copyValue(IndexInt from, IndexInt to)
1202 {
1203 get(to) = get(from);
1204 }
1205 void initNewValue(IndexInt idx, Vec3 pos);
1206
1207 //! python interface (similar to grid data)
1208 ParticleDataImpl<T> ©From(const ParticleDataImpl<T> &a);
_W_25(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1209 static PyObject *_W_25(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1210 {
1211 try {
1212 PbArgs _args(_linargs, _kwds);
1213 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1214 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1215 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::copyFrom", !noTiming);
1216 PyObject *_retval = 0;
1217 {
1218 ArgLocker _lock;
1219 const ParticleDataImpl<T> &a = *_args.getPtr<ParticleDataImpl<T>>("a", 0, &_lock);
1220 pbo->_args.copy(_args);
1221 _retval = toPy(pbo->copyFrom(a));
1222 pbo->_args.check();
1223 }
1224 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::copyFrom", !noTiming);
1225 return _retval;
1226 }
1227 catch (std::exception &e) {
1228 pbSetError("ParticleDataImpl::copyFrom", e.what());
1229 return 0;
1230 }
1231 }
1232
1233 void setConst(const T &s);
_W_26(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1234 static PyObject *_W_26(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1235 {
1236 try {
1237 PbArgs _args(_linargs, _kwds);
1238 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1239 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1240 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::setConst", !noTiming);
1241 PyObject *_retval = 0;
1242 {
1243 ArgLocker _lock;
1244 const T &s = *_args.getPtr<T>("s", 0, &_lock);
1245 pbo->_args.copy(_args);
1246 _retval = getPyNone();
1247 pbo->setConst(s);
1248 pbo->_args.check();
1249 }
1250 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::setConst", !noTiming);
1251 return _retval;
1252 }
1253 catch (std::exception &e) {
1254 pbSetError("ParticleDataImpl::setConst", e.what());
1255 return 0;
1256 }
1257 }
1258
1259 void setConstRange(const T &s, const int begin, const int end);
_W_27(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1260 static PyObject *_W_27(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1261 {
1262 try {
1263 PbArgs _args(_linargs, _kwds);
1264 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1265 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1266 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::setConstRange", !noTiming);
1267 PyObject *_retval = 0;
1268 {
1269 ArgLocker _lock;
1270 const T &s = *_args.getPtr<T>("s", 0, &_lock);
1271 const int begin = _args.get<int>("begin", 1, &_lock);
1272 const int end = _args.get<int>("end", 2, &_lock);
1273 pbo->_args.copy(_args);
1274 _retval = getPyNone();
1275 pbo->setConstRange(s, begin, end);
1276 pbo->_args.check();
1277 }
1278 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::setConstRange", !noTiming);
1279 return _retval;
1280 }
1281 catch (std::exception &e) {
1282 pbSetError("ParticleDataImpl::setConstRange", e.what());
1283 return 0;
1284 }
1285 }
1286
1287 void add(const ParticleDataImpl<T> &a);
_W_28(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1288 static PyObject *_W_28(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1289 {
1290 try {
1291 PbArgs _args(_linargs, _kwds);
1292 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1293 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1294 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::add", !noTiming);
1295 PyObject *_retval = 0;
1296 {
1297 ArgLocker _lock;
1298 const ParticleDataImpl<T> &a = *_args.getPtr<ParticleDataImpl<T>>("a", 0, &_lock);
1299 pbo->_args.copy(_args);
1300 _retval = getPyNone();
1301 pbo->add(a);
1302 pbo->_args.check();
1303 }
1304 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::add", !noTiming);
1305 return _retval;
1306 }
1307 catch (std::exception &e) {
1308 pbSetError("ParticleDataImpl::add", e.what());
1309 return 0;
1310 }
1311 }
1312
1313 void sub(const ParticleDataImpl<T> &a);
_W_29(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1314 static PyObject *_W_29(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1315 {
1316 try {
1317 PbArgs _args(_linargs, _kwds);
1318 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1319 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1320 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::sub", !noTiming);
1321 PyObject *_retval = 0;
1322 {
1323 ArgLocker _lock;
1324 const ParticleDataImpl<T> &a = *_args.getPtr<ParticleDataImpl<T>>("a", 0, &_lock);
1325 pbo->_args.copy(_args);
1326 _retval = getPyNone();
1327 pbo->sub(a);
1328 pbo->_args.check();
1329 }
1330 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::sub", !noTiming);
1331 return _retval;
1332 }
1333 catch (std::exception &e) {
1334 pbSetError("ParticleDataImpl::sub", e.what());
1335 return 0;
1336 }
1337 }
1338
1339 void addConst(const T &s);
_W_30(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1340 static PyObject *_W_30(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1341 {
1342 try {
1343 PbArgs _args(_linargs, _kwds);
1344 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1345 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1346 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::addConst", !noTiming);
1347 PyObject *_retval = 0;
1348 {
1349 ArgLocker _lock;
1350 const T &s = *_args.getPtr<T>("s", 0, &_lock);
1351 pbo->_args.copy(_args);
1352 _retval = getPyNone();
1353 pbo->addConst(s);
1354 pbo->_args.check();
1355 }
1356 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::addConst", !noTiming);
1357 return _retval;
1358 }
1359 catch (std::exception &e) {
1360 pbSetError("ParticleDataImpl::addConst", e.what());
1361 return 0;
1362 }
1363 }
1364
1365 void addScaled(const ParticleDataImpl<T> &a, const T &factor);
_W_31(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1366 static PyObject *_W_31(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1367 {
1368 try {
1369 PbArgs _args(_linargs, _kwds);
1370 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1371 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1372 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::addScaled", !noTiming);
1373 PyObject *_retval = 0;
1374 {
1375 ArgLocker _lock;
1376 const ParticleDataImpl<T> &a = *_args.getPtr<ParticleDataImpl<T>>("a", 0, &_lock);
1377 const T &factor = *_args.getPtr<T>("factor", 1, &_lock);
1378 pbo->_args.copy(_args);
1379 _retval = getPyNone();
1380 pbo->addScaled(a, factor);
1381 pbo->_args.check();
1382 }
1383 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::addScaled", !noTiming);
1384 return _retval;
1385 }
1386 catch (std::exception &e) {
1387 pbSetError("ParticleDataImpl::addScaled", e.what());
1388 return 0;
1389 }
1390 }
1391
1392 void mult(const ParticleDataImpl<T> &a);
_W_32(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1393 static PyObject *_W_32(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1394 {
1395 try {
1396 PbArgs _args(_linargs, _kwds);
1397 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1398 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1399 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::mult", !noTiming);
1400 PyObject *_retval = 0;
1401 {
1402 ArgLocker _lock;
1403 const ParticleDataImpl<T> &a = *_args.getPtr<ParticleDataImpl<T>>("a", 0, &_lock);
1404 pbo->_args.copy(_args);
1405 _retval = getPyNone();
1406 pbo->mult(a);
1407 pbo->_args.check();
1408 }
1409 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::mult", !noTiming);
1410 return _retval;
1411 }
1412 catch (std::exception &e) {
1413 pbSetError("ParticleDataImpl::mult", e.what());
1414 return 0;
1415 }
1416 }
1417
1418 void multConst(const T &s);
_W_33(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1419 static PyObject *_W_33(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1420 {
1421 try {
1422 PbArgs _args(_linargs, _kwds);
1423 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1424 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1425 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::multConst", !noTiming);
1426 PyObject *_retval = 0;
1427 {
1428 ArgLocker _lock;
1429 const T &s = *_args.getPtr<T>("s", 0, &_lock);
1430 pbo->_args.copy(_args);
1431 _retval = getPyNone();
1432 pbo->multConst(s);
1433 pbo->_args.check();
1434 }
1435 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::multConst", !noTiming);
1436 return _retval;
1437 }
1438 catch (std::exception &e) {
1439 pbSetError("ParticleDataImpl::multConst", e.what());
1440 return 0;
1441 }
1442 }
1443
1444 void safeDiv(const ParticleDataImpl<T> &a);
_W_34(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1445 static PyObject *_W_34(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1446 {
1447 try {
1448 PbArgs _args(_linargs, _kwds);
1449 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1450 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1451 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::safeDiv", !noTiming);
1452 PyObject *_retval = 0;
1453 {
1454 ArgLocker _lock;
1455 const ParticleDataImpl<T> &a = *_args.getPtr<ParticleDataImpl<T>>("a", 0, &_lock);
1456 pbo->_args.copy(_args);
1457 _retval = getPyNone();
1458 pbo->safeDiv(a);
1459 pbo->_args.check();
1460 }
1461 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::safeDiv", !noTiming);
1462 return _retval;
1463 }
1464 catch (std::exception &e) {
1465 pbSetError("ParticleDataImpl::safeDiv", e.what());
1466 return 0;
1467 }
1468 }
1469
1470 void clamp(const Real vmin, const Real vmax);
_W_35(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1471 static PyObject *_W_35(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1472 {
1473 try {
1474 PbArgs _args(_linargs, _kwds);
1475 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1476 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1477 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::clamp", !noTiming);
1478 PyObject *_retval = 0;
1479 {
1480 ArgLocker _lock;
1481 const Real vmin = _args.get<Real>("vmin", 0, &_lock);
1482 const Real vmax = _args.get<Real>("vmax", 1, &_lock);
1483 pbo->_args.copy(_args);
1484 _retval = getPyNone();
1485 pbo->clamp(vmin, vmax);
1486 pbo->_args.check();
1487 }
1488 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::clamp", !noTiming);
1489 return _retval;
1490 }
1491 catch (std::exception &e) {
1492 pbSetError("ParticleDataImpl::clamp", e.what());
1493 return 0;
1494 }
1495 }
1496
1497 void clampMin(const Real vmin);
_W_36(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1498 static PyObject *_W_36(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1499 {
1500 try {
1501 PbArgs _args(_linargs, _kwds);
1502 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1503 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1504 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::clampMin", !noTiming);
1505 PyObject *_retval = 0;
1506 {
1507 ArgLocker _lock;
1508 const Real vmin = _args.get<Real>("vmin", 0, &_lock);
1509 pbo->_args.copy(_args);
1510 _retval = getPyNone();
1511 pbo->clampMin(vmin);
1512 pbo->_args.check();
1513 }
1514 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::clampMin", !noTiming);
1515 return _retval;
1516 }
1517 catch (std::exception &e) {
1518 pbSetError("ParticleDataImpl::clampMin", e.what());
1519 return 0;
1520 }
1521 }
1522
1523 void clampMax(const Real vmax);
_W_37(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1524 static PyObject *_W_37(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1525 {
1526 try {
1527 PbArgs _args(_linargs, _kwds);
1528 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1529 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1530 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::clampMax", !noTiming);
1531 PyObject *_retval = 0;
1532 {
1533 ArgLocker _lock;
1534 const Real vmax = _args.get<Real>("vmax", 0, &_lock);
1535 pbo->_args.copy(_args);
1536 _retval = getPyNone();
1537 pbo->clampMax(vmax);
1538 pbo->_args.check();
1539 }
1540 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::clampMax", !noTiming);
1541 return _retval;
1542 }
1543 catch (std::exception &e) {
1544 pbSetError("ParticleDataImpl::clampMax", e.what());
1545 return 0;
1546 }
1547 }
1548
1549 Real getMaxAbs() const;
_W_38(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1550 static PyObject *_W_38(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1551 {
1552 try {
1553 PbArgs _args(_linargs, _kwds);
1554 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1555 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1556 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::getMaxAbs", !noTiming);
1557 PyObject *_retval = 0;
1558 {
1559 ArgLocker _lock;
1560 pbo->_args.copy(_args);
1561 _retval = toPy(pbo->getMaxAbs());
1562 pbo->_args.check();
1563 }
1564 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::getMaxAbs", !noTiming);
1565 return _retval;
1566 }
1567 catch (std::exception &e) {
1568 pbSetError("ParticleDataImpl::getMaxAbs", e.what());
1569 return 0;
1570 }
1571 }
1572
1573 Real getMax() const;
_W_39(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1574 static PyObject *_W_39(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1575 {
1576 try {
1577 PbArgs _args(_linargs, _kwds);
1578 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1579 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1580 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::getMax", !noTiming);
1581 PyObject *_retval = 0;
1582 {
1583 ArgLocker _lock;
1584 pbo->_args.copy(_args);
1585 _retval = toPy(pbo->getMax());
1586 pbo->_args.check();
1587 }
1588 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::getMax", !noTiming);
1589 return _retval;
1590 }
1591 catch (std::exception &e) {
1592 pbSetError("ParticleDataImpl::getMax", e.what());
1593 return 0;
1594 }
1595 }
1596
1597 Real getMin() const;
_W_40(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1598 static PyObject *_W_40(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1599 {
1600 try {
1601 PbArgs _args(_linargs, _kwds);
1602 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1603 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1604 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::getMin", !noTiming);
1605 PyObject *_retval = 0;
1606 {
1607 ArgLocker _lock;
1608 pbo->_args.copy(_args);
1609 _retval = toPy(pbo->getMin());
1610 pbo->_args.check();
1611 }
1612 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::getMin", !noTiming);
1613 return _retval;
1614 }
1615 catch (std::exception &e) {
1616 pbSetError("ParticleDataImpl::getMin", e.what());
1617 return 0;
1618 }
1619 }
1620
1621 T sum(const ParticleDataImpl<int> *t = NULL, const int itype = 0) const;
_W_41(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1622 static PyObject *_W_41(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1623 {
1624 try {
1625 PbArgs _args(_linargs, _kwds);
1626 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1627 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1628 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::sum", !noTiming);
1629 PyObject *_retval = 0;
1630 {
1631 ArgLocker _lock;
1632 const ParticleDataImpl<int> *t = _args.getPtrOpt<ParticleDataImpl<int>>(
1633 "t", 0, NULL, &_lock);
1634 const int itype = _args.getOpt<int>("itype", 1, 0, &_lock);
1635 pbo->_args.copy(_args);
1636 _retval = toPy(pbo->sum(t, itype));
1637 pbo->_args.check();
1638 }
1639 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::sum", !noTiming);
1640 return _retval;
1641 }
1642 catch (std::exception &e) {
1643 pbSetError("ParticleDataImpl::sum", e.what());
1644 return 0;
1645 }
1646 }
1647
1648 Real sumSquare() const;
_W_42(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1649 static PyObject *_W_42(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1650 {
1651 try {
1652 PbArgs _args(_linargs, _kwds);
1653 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1654 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1655 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::sumSquare", !noTiming);
1656 PyObject *_retval = 0;
1657 {
1658 ArgLocker _lock;
1659 pbo->_args.copy(_args);
1660 _retval = toPy(pbo->sumSquare());
1661 pbo->_args.check();
1662 }
1663 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::sumSquare", !noTiming);
1664 return _retval;
1665 }
1666 catch (std::exception &e) {
1667 pbSetError("ParticleDataImpl::sumSquare", e.what());
1668 return 0;
1669 }
1670 }
1671
1672 Real sumMagnitude() const;
_W_43(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1673 static PyObject *_W_43(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1674 {
1675 try {
1676 PbArgs _args(_linargs, _kwds);
1677 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1678 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1679 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::sumMagnitude", !noTiming);
1680 PyObject *_retval = 0;
1681 {
1682 ArgLocker _lock;
1683 pbo->_args.copy(_args);
1684 _retval = toPy(pbo->sumMagnitude());
1685 pbo->_args.check();
1686 }
1687 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::sumMagnitude", !noTiming);
1688 return _retval;
1689 }
1690 catch (std::exception &e) {
1691 pbSetError("ParticleDataImpl::sumMagnitude", e.what());
1692 return 0;
1693 }
1694 }
1695
1696 //! special, set if int flag in t has "flag"
1697 void setConstIntFlag(const T &s, const ParticleDataImpl<int> &t, const int flag);
_W_44(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1698 static PyObject *_W_44(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1699 {
1700 try {
1701 PbArgs _args(_linargs, _kwds);
1702 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1703 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1704 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::setConstIntFlag", !noTiming);
1705 PyObject *_retval = 0;
1706 {
1707 ArgLocker _lock;
1708 const T &s = *_args.getPtr<T>("s", 0, &_lock);
1709 const ParticleDataImpl<int> &t = *_args.getPtr<ParticleDataImpl<int>>("t", 1, &_lock);
1710 const int flag = _args.get<int>("flag", 2, &_lock);
1711 pbo->_args.copy(_args);
1712 _retval = getPyNone();
1713 pbo->setConstIntFlag(s, t, flag);
1714 pbo->_args.check();
1715 }
1716 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::setConstIntFlag", !noTiming);
1717 return _retval;
1718 }
1719 catch (std::exception &e) {
1720 pbSetError("ParticleDataImpl::setConstIntFlag", e.what());
1721 return 0;
1722 }
1723 }
1724
1725 void printPdata(IndexInt start = -1, IndexInt stop = -1, bool printIndex = false);
_W_45(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1726 static PyObject *_W_45(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1727 {
1728 try {
1729 PbArgs _args(_linargs, _kwds);
1730 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1731 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1732 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::printPdata", !noTiming);
1733 PyObject *_retval = 0;
1734 {
1735 ArgLocker _lock;
1736 IndexInt start = _args.getOpt<IndexInt>("start", 0, -1, &_lock);
1737 IndexInt stop = _args.getOpt<IndexInt>("stop", 1, -1, &_lock);
1738 bool printIndex = _args.getOpt<bool>("printIndex", 2, false, &_lock);
1739 pbo->_args.copy(_args);
1740 _retval = getPyNone();
1741 pbo->printPdata(start, stop, printIndex);
1742 pbo->_args.check();
1743 }
1744 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::printPdata", !noTiming);
1745 return _retval;
1746 }
1747 catch (std::exception &e) {
1748 pbSetError("ParticleDataImpl::printPdata", e.what());
1749 return 0;
1750 }
1751 }
1752
1753 //! file io
1754 int save(const std::string name);
_W_46(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1755 static PyObject *_W_46(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1756 {
1757 try {
1758 PbArgs _args(_linargs, _kwds);
1759 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1760 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1761 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::save", !noTiming);
1762 PyObject *_retval = 0;
1763 {
1764 ArgLocker _lock;
1765 const std::string name = _args.get<std::string>("name", 0, &_lock);
1766 pbo->_args.copy(_args);
1767 _retval = toPy(pbo->save(name));
1768 pbo->_args.check();
1769 }
1770 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::save", !noTiming);
1771 return _retval;
1772 }
1773 catch (std::exception &e) {
1774 pbSetError("ParticleDataImpl::save", e.what());
1775 return 0;
1776 }
1777 }
1778
1779 int load(const std::string name);
_W_47(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1780 static PyObject *_W_47(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1781 {
1782 try {
1783 PbArgs _args(_linargs, _kwds);
1784 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1785 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1786 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::load", !noTiming);
1787 PyObject *_retval = 0;
1788 {
1789 ArgLocker _lock;
1790 const std::string name = _args.get<std::string>("name", 0, &_lock);
1791 pbo->_args.copy(_args);
1792 _retval = toPy(pbo->load(name));
1793 pbo->_args.check();
1794 }
1795 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::load", !noTiming);
1796 return _retval;
1797 }
1798 catch (std::exception &e) {
1799 pbSetError("ParticleDataImpl::load", e.what());
1800 return 0;
1801 }
1802 }
1803
1804 //! get data pointer of particle data
1805 std::string getDataPointer();
_W_48(PyObject * _self,PyObject * _linargs,PyObject * _kwds)1806 static PyObject *_W_48(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
1807 {
1808 try {
1809 PbArgs _args(_linargs, _kwds);
1810 ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
1811 bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
1812 pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::getDataPointer", !noTiming);
1813 PyObject *_retval = 0;
1814 {
1815 ArgLocker _lock;
1816 pbo->_args.copy(_args);
1817 _retval = toPy(pbo->getDataPointer());
1818 pbo->_args.check();
1819 }
1820 pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::getDataPointer", !noTiming);
1821 return _retval;
1822 }
1823 catch (std::exception &e) {
1824 pbSetError("ParticleDataImpl::getDataPointer", e.what());
1825 return 0;
1826 }
1827 }
1828
1829 protected:
1830 //! data storage
1831 std::vector<T> mData;
1832
1833 //! optionally , we might have an associated grid from which to grab new data
1834 Grid<T> *mpGridSource; //! unfortunately , we need to distinguish mac vs regular vec3
1835 bool mGridSourceMAC;
1836 public:
1837 PbArgs _args;
1838 }
1839 #define _C_ParticleDataImpl
1840 ;
1841
1842 //******************************************************************************
1843 // Implementation
1844 //******************************************************************************
1845
1846 const int DELETE_PART = 20; // chunk size for compression
1847
addBuffered(const Vec3 & pos,int flag)1848 void ParticleBase::addBuffered(const Vec3 &pos, int flag)
1849 {
1850 mNewBufferPos.push_back(pos);
1851 mNewBufferFlag.push_back(flag);
1852 }
1853
clear()1854 template<class S> void ParticleSystem<S>::clear()
1855 {
1856 mDeleteChunk = mDeletes = 0;
1857 this->resizeAll(0); // instead of mData.clear
1858 }
1859
add(const S & data)1860 template<class S> IndexInt ParticleSystem<S>::add(const S &data)
1861 {
1862 mData.push_back(data);
1863 mDeleteChunk = mData.size() / DELETE_PART;
1864 this->addAllPdata();
1865 return mData.size() - 1;
1866 }
1867
kill(IndexInt idx)1868 template<class S> inline void ParticleSystem<S>::kill(IndexInt idx)
1869 {
1870 assertMsg(idx >= 0 && idx < size(), "Index out of bounds");
1871 mData[idx].flag |= PDELETE;
1872 if ((++mDeletes > mDeleteChunk) && (mAllowCompress))
1873 compress();
1874 }
1875
getPosPdata(ParticleDataImpl<Vec3> & target)1876 template<class S> void ParticleSystem<S>::getPosPdata(ParticleDataImpl<Vec3> &target) const
1877 {
1878 for (IndexInt i = 0; i < (IndexInt)this->size(); ++i) {
1879 target[i] = this->getPos(i);
1880 }
1881 }
setPosPdata(const ParticleDataImpl<Vec3> & source)1882 template<class S> void ParticleSystem<S>::setPosPdata(const ParticleDataImpl<Vec3> &source)
1883 {
1884 for (IndexInt i = 0; i < (IndexInt)this->size(); ++i) {
1885 this->setPos(i, source[i]);
1886 }
1887 }
1888
transformPositions(Vec3i dimOld,Vec3i dimNew)1889 template<class S> void ParticleSystem<S>::transformPositions(Vec3i dimOld, Vec3i dimNew)
1890 {
1891 const Vec3 factor = calcGridSizeFactor(dimNew, dimOld);
1892 for (IndexInt i = 0; i < (IndexInt)this->size(); ++i) {
1893 this->setPos(i, this->getPos(i) * factor);
1894 }
1895 }
1896
1897 // check for deletion/invalid position, otherwise return velocity
1898
1899 template<class S> struct _GridAdvectKernel : public KernelBase {
_GridAdvectKernel_GridAdvectKernel1900 _GridAdvectKernel(const KernelBase &base,
1901 std::vector<S> &p,
1902 const MACGrid &vel,
1903 const FlagGrid &flags,
1904 const Real dt,
1905 const bool deleteInObstacle,
1906 const bool stopInObstacle,
1907 const bool skipNew,
1908 const ParticleDataImpl<int> *ptype,
1909 const int exclude,
1910 std::vector<Vec3> &u)
1911 : KernelBase(base),
1912 p(p),
1913 vel(vel),
1914 flags(flags),
1915 dt(dt),
1916 deleteInObstacle(deleteInObstacle),
1917 stopInObstacle(stopInObstacle),
1918 skipNew(skipNew),
1919 ptype(ptype),
1920 exclude(exclude),
1921 u(u)
1922 {
1923 }
op_GridAdvectKernel1924 inline void op(IndexInt idx,
1925 std::vector<S> &p,
1926 const MACGrid &vel,
1927 const FlagGrid &flags,
1928 const Real dt,
1929 const bool deleteInObstacle,
1930 const bool stopInObstacle,
1931 const bool skipNew,
1932 const ParticleDataImpl<int> *ptype,
1933 const int exclude,
1934 std::vector<Vec3> &u) const
1935 {
1936 if ((p[idx].flag & ParticleBase::PDELETE) || (ptype && ((*ptype)[idx] & exclude)) ||
1937 (skipNew && (p[idx].flag & ParticleBase::PNEW))) {
1938 u[idx] = 0.;
1939 return;
1940 }
1941 // special handling
1942 if (deleteInObstacle || stopInObstacle) {
1943 if (!flags.isInBounds(p[idx].pos, 1) || flags.isObstacle(p[idx].pos)) {
1944 if (stopInObstacle)
1945 u[idx] = 0.;
1946 // for simple tracer particles, its convenient to delete particles right away
1947 // for other sim types, eg flip, we can try to fix positions later on
1948 if (deleteInObstacle)
1949 p[idx].flag |= ParticleBase::PDELETE;
1950 return;
1951 }
1952 }
1953 u[idx] = vel.getInterpolated(p[idx].pos) * dt;
1954 }
operator_GridAdvectKernel1955 void operator()(const tbb::blocked_range<IndexInt> &__r) const
1956 {
1957 for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
1958 op(idx, p, vel, flags, dt, deleteInObstacle, stopInObstacle, skipNew, ptype, exclude, u);
1959 }
run_GridAdvectKernel1960 void run()
1961 {
1962 tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
1963 }
1964 std::vector<S> &p;
1965 const MACGrid &vel;
1966 const FlagGrid &flags;
1967 const Real dt;
1968 const bool deleteInObstacle;
1969 const bool stopInObstacle;
1970 const bool skipNew;
1971 const ParticleDataImpl<int> *ptype;
1972 const int exclude;
1973 std::vector<Vec3> &u;
1974 };
1975 template<class S> struct GridAdvectKernel : public KernelBase {
GridAdvectKernelGridAdvectKernel1976 GridAdvectKernel(std::vector<S> &p,
1977 const MACGrid &vel,
1978 const FlagGrid &flags,
1979 const Real dt,
1980 const bool deleteInObstacle,
1981 const bool stopInObstacle,
1982 const bool skipNew,
1983 const ParticleDataImpl<int> *ptype,
1984 const int exclude)
1985 : KernelBase(p.size()),
1986 _inner(KernelBase(p.size()),
1987 p,
1988 vel,
1989 flags,
1990 dt,
1991 deleteInObstacle,
1992 stopInObstacle,
1993 skipNew,
1994 ptype,
1995 exclude,
1996 u),
1997 p(p),
1998 vel(vel),
1999 flags(flags),
2000 dt(dt),
2001 deleteInObstacle(deleteInObstacle),
2002 stopInObstacle(stopInObstacle),
2003 skipNew(skipNew),
2004 ptype(ptype),
2005 exclude(exclude),
2006 u((size))
2007 {
2008 runMessage();
2009 run();
2010 }
runGridAdvectKernel2011 void run()
2012 {
2013 _inner.run();
2014 }
2015 inline operator std::vector<Vec3>()
2016 {
2017 return u;
2018 }
getRetGridAdvectKernel2019 inline std::vector<Vec3> &getRet()
2020 {
2021 return u;
2022 }
getArg0GridAdvectKernel2023 inline std::vector<S> &getArg0()
2024 {
2025 return p;
2026 }
2027 typedef std::vector<S> type0;
getArg1GridAdvectKernel2028 inline const MACGrid &getArg1()
2029 {
2030 return vel;
2031 }
2032 typedef MACGrid type1;
getArg2GridAdvectKernel2033 inline const FlagGrid &getArg2()
2034 {
2035 return flags;
2036 }
2037 typedef FlagGrid type2;
getArg3GridAdvectKernel2038 inline const Real &getArg3()
2039 {
2040 return dt;
2041 }
2042 typedef Real type3;
getArg4GridAdvectKernel2043 inline const bool &getArg4()
2044 {
2045 return deleteInObstacle;
2046 }
2047 typedef bool type4;
getArg5GridAdvectKernel2048 inline const bool &getArg5()
2049 {
2050 return stopInObstacle;
2051 }
2052 typedef bool type5;
getArg6GridAdvectKernel2053 inline const bool &getArg6()
2054 {
2055 return skipNew;
2056 }
2057 typedef bool type6;
getArg7GridAdvectKernel2058 inline const ParticleDataImpl<int> *getArg7()
2059 {
2060 return ptype;
2061 }
2062 typedef ParticleDataImpl<int> type7;
getArg8GridAdvectKernel2063 inline const int &getArg8()
2064 {
2065 return exclude;
2066 }
2067 typedef int type8;
runMessageGridAdvectKernel2068 void runMessage()
2069 {
2070 debMsg("Executing kernel GridAdvectKernel ", 3);
2071 debMsg("Kernel range"
2072 << " size " << size << " ",
2073 4);
2074 };
2075 _GridAdvectKernel<S> _inner;
2076 std::vector<S> &p;
2077 const MACGrid &vel;
2078 const FlagGrid &flags;
2079 const Real dt;
2080 const bool deleteInObstacle;
2081 const bool stopInObstacle;
2082 const bool skipNew;
2083 const ParticleDataImpl<int> *ptype;
2084 const int exclude;
2085 std::vector<Vec3> u;
2086 };
2087 ;
2088
2089 // final check after advection to make sure particles haven't escaped
2090 // (similar to particle advection kernel)
2091
2092 template<class S> struct KnDeleteInObstacle : public KernelBase {
KnDeleteInObstacleKnDeleteInObstacle2093 KnDeleteInObstacle(std::vector<S> &p, const FlagGrid &flags)
2094 : KernelBase(p.size()), p(p), flags(flags)
2095 {
2096 runMessage();
2097 run();
2098 }
opKnDeleteInObstacle2099 inline void op(IndexInt idx, std::vector<S> &p, const FlagGrid &flags) const
2100 {
2101 if (p[idx].flag & ParticleBase::PDELETE)
2102 return;
2103 if (!flags.isInBounds(p[idx].pos, 1) || flags.isObstacle(p[idx].pos)) {
2104 p[idx].flag |= ParticleBase::PDELETE;
2105 }
2106 }
getArg0KnDeleteInObstacle2107 inline std::vector<S> &getArg0()
2108 {
2109 return p;
2110 }
2111 typedef std::vector<S> type0;
getArg1KnDeleteInObstacle2112 inline const FlagGrid &getArg1()
2113 {
2114 return flags;
2115 }
2116 typedef FlagGrid type1;
runMessageKnDeleteInObstacle2117 void runMessage()
2118 {
2119 debMsg("Executing kernel KnDeleteInObstacle ", 3);
2120 debMsg("Kernel range"
2121 << " size " << size << " ",
2122 4);
2123 };
operatorKnDeleteInObstacle2124 void operator()(const tbb::blocked_range<IndexInt> &__r) const
2125 {
2126 for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
2127 op(idx, p, flags);
2128 }
runKnDeleteInObstacle2129 void run()
2130 {
2131 tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
2132 }
2133 std::vector<S> &p;
2134 const FlagGrid &flags;
2135 };
2136
2137 // try to get closer to actual obstacle boundary
bisectBacktracePos(const FlagGrid & flags,const Vec3 & oldp,const Vec3 & newp)2138 static inline Vec3 bisectBacktracePos(const FlagGrid &flags, const Vec3 &oldp, const Vec3 &newp)
2139 {
2140 Real s = 0.;
2141 for (int i = 1; i < 5; ++i) {
2142 Real ds = 1. / (Real)(1 << i);
2143 if (!flags.isObstacle(oldp * (1. - (s + ds)) + newp * (s + ds))) {
2144 s += ds;
2145 }
2146 }
2147 return (oldp * (1. - (s)) + newp * (s));
2148 }
2149
2150 // at least make sure all particles are inside domain
2151
2152 template<class S> struct KnClampPositions : public KernelBase {
2153 KnClampPositions(std::vector<S> &p,
2154 const FlagGrid &flags,
2155 ParticleDataImpl<Vec3> *posOld = NULL,
2156 bool stopInObstacle = true,
2157 const ParticleDataImpl<int> *ptype = NULL,
2158 const int exclude = 0)
2159 : KernelBase(p.size()),
2160 p(p),
2161 flags(flags),
2162 posOld(posOld),
2163 stopInObstacle(stopInObstacle),
2164 ptype(ptype),
2165 exclude(exclude)
2166 {
2167 runMessage();
2168 run();
2169 }
2170 inline void op(IndexInt idx,
2171 std::vector<S> &p,
2172 const FlagGrid &flags,
2173 ParticleDataImpl<Vec3> *posOld = NULL,
2174 bool stopInObstacle = true,
2175 const ParticleDataImpl<int> *ptype = NULL,
2176 const int exclude = 0) const
2177 {
2178 if (p[idx].flag & ParticleBase::PDELETE)
2179 return;
2180 if (ptype && ((*ptype)[idx] & exclude)) {
2181 if (posOld)
2182 p[idx].pos = (*posOld)[idx];
2183 return;
2184 }
2185 if (!flags.isInBounds(p[idx].pos, 0)) {
2186 p[idx].pos = clamp(p[idx].pos, Vec3(0.), toVec3(flags.getSize()) - Vec3(1.));
2187 }
2188 if (stopInObstacle && (flags.isObstacle(p[idx].pos))) {
2189 p[idx].pos = bisectBacktracePos(flags, (*posOld)[idx], p[idx].pos);
2190 }
2191 }
getArg0KnClampPositions2192 inline std::vector<S> &getArg0()
2193 {
2194 return p;
2195 }
2196 typedef std::vector<S> type0;
getArg1KnClampPositions2197 inline const FlagGrid &getArg1()
2198 {
2199 return flags;
2200 }
2201 typedef FlagGrid type1;
getArg2KnClampPositions2202 inline ParticleDataImpl<Vec3> *getArg2()
2203 {
2204 return posOld;
2205 }
2206 typedef ParticleDataImpl<Vec3> type2;
getArg3KnClampPositions2207 inline bool &getArg3()
2208 {
2209 return stopInObstacle;
2210 }
2211 typedef bool type3;
getArg4KnClampPositions2212 inline const ParticleDataImpl<int> *getArg4()
2213 {
2214 return ptype;
2215 }
2216 typedef ParticleDataImpl<int> type4;
getArg5KnClampPositions2217 inline const int &getArg5()
2218 {
2219 return exclude;
2220 }
2221 typedef int type5;
runMessageKnClampPositions2222 void runMessage()
2223 {
2224 debMsg("Executing kernel KnClampPositions ", 3);
2225 debMsg("Kernel range"
2226 << " size " << size << " ",
2227 4);
2228 };
operatorKnClampPositions2229 void operator()(const tbb::blocked_range<IndexInt> &__r) const
2230 {
2231 for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
2232 op(idx, p, flags, posOld, stopInObstacle, ptype, exclude);
2233 }
runKnClampPositions2234 void run()
2235 {
2236 tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
2237 }
2238 std::vector<S> &p;
2239 const FlagGrid &flags;
2240 ParticleDataImpl<Vec3> *posOld;
2241 bool stopInObstacle;
2242 const ParticleDataImpl<int> *ptype;
2243 const int exclude;
2244 };
2245
2246 // advection plugin
2247 template<class S>
advectInGrid(const FlagGrid & flags,const MACGrid & vel,const int integrationMode,const bool deleteInObstacle,const bool stopInObstacle,const bool skipNew,const ParticleDataImpl<int> * ptype,const int exclude)2248 void ParticleSystem<S>::advectInGrid(const FlagGrid &flags,
2249 const MACGrid &vel,
2250 const int integrationMode,
2251 const bool deleteInObstacle,
2252 const bool stopInObstacle,
2253 const bool skipNew,
2254 const ParticleDataImpl<int> *ptype,
2255 const int exclude)
2256 {
2257 // position clamp requires old positions, backup
2258 ParticleDataImpl<Vec3> *posOld = NULL;
2259 if (!deleteInObstacle) {
2260 posOld = new ParticleDataImpl<Vec3>(this->getParent());
2261 posOld->resize(mData.size());
2262 for (IndexInt i = 0; i < (IndexInt)mData.size(); ++i)
2263 (*posOld)[i] = mData[i].pos;
2264 }
2265
2266 // update positions
2267 GridAdvectKernel<S> kernel(mData,
2268 vel,
2269 flags,
2270 getParent()->getDt(),
2271 deleteInObstacle,
2272 stopInObstacle,
2273 skipNew,
2274 ptype,
2275 exclude);
2276 integratePointSet(kernel, integrationMode);
2277
2278 if (!deleteInObstacle) {
2279 KnClampPositions<S>(mData, flags, posOld, stopInObstacle, ptype, exclude);
2280 delete posOld;
2281 }
2282 else {
2283 KnDeleteInObstacle<S>(mData, flags);
2284 }
2285 }
2286
2287 template<class S> struct KnProjectParticles : public KernelBase {
KnProjectParticlesKnProjectParticles2288 KnProjectParticles(ParticleSystem<S> &part, Grid<Vec3> &gradient)
2289 : KernelBase(part.size()), part(part), gradient(gradient)
2290 {
2291 runMessage();
2292 run();
2293 }
opKnProjectParticles2294 inline void op(IndexInt idx, ParticleSystem<S> &part, Grid<Vec3> &gradient)
2295 {
2296 static RandomStream rand(3123984);
2297 const double jlen = 0.1;
2298
2299 if (part.isActive(idx)) {
2300 // project along levelset gradient
2301 Vec3 p = part[idx].pos;
2302 if (gradient.isInBounds(p)) {
2303 Vec3 n = gradient.getInterpolated(p);
2304 Real dist = normalize(n);
2305 Vec3 dx = n * (-dist + jlen * (1 + rand.getReal()));
2306 p += dx;
2307 }
2308 // clamp to outer boundaries (+jitter)
2309 const double jlen = 0.1;
2310 Vec3 jitter = jlen * rand.getVec3();
2311 part[idx].pos = clamp(p, Vec3(1, 1, 1) + jitter, toVec3(gradient.getSize() - 1) - jitter);
2312 }
2313 }
getArg0KnProjectParticles2314 inline ParticleSystem<S> &getArg0()
2315 {
2316 return part;
2317 }
2318 typedef ParticleSystem<S> type0;
getArg1KnProjectParticles2319 inline Grid<Vec3> &getArg1()
2320 {
2321 return gradient;
2322 }
2323 typedef Grid<Vec3> type1;
runMessageKnProjectParticles2324 void runMessage()
2325 {
2326 debMsg("Executing kernel KnProjectParticles ", 3);
2327 debMsg("Kernel range"
2328 << " size " << size << " ",
2329 4);
2330 };
runKnProjectParticles2331 void run()
2332 {
2333 const IndexInt _sz = size;
2334 for (IndexInt i = 0; i < _sz; i++)
2335 op(i, part, gradient);
2336 }
2337 ParticleSystem<S> ∂
2338 Grid<Vec3> &gradient;
2339 };
2340
projectOutside(Grid<Vec3> & gradient)2341 template<class S> void ParticleSystem<S>::projectOutside(Grid<Vec3> &gradient)
2342 {
2343 KnProjectParticles<S>(*this, gradient);
2344 }
2345
2346 template<class S> struct KnProjectOutOfBnd : public KernelBase {
KnProjectOutOfBndKnProjectOutOfBnd2347 KnProjectOutOfBnd(ParticleSystem<S> &part,
2348 const FlagGrid &flags,
2349 const Real bnd,
2350 const bool *axis,
2351 const ParticleDataImpl<int> *ptype,
2352 const int exclude)
2353 : KernelBase(part.size()),
2354 part(part),
2355 flags(flags),
2356 bnd(bnd),
2357 axis(axis),
2358 ptype(ptype),
2359 exclude(exclude)
2360 {
2361 runMessage();
2362 run();
2363 }
opKnProjectOutOfBnd2364 inline void op(IndexInt idx,
2365 ParticleSystem<S> &part,
2366 const FlagGrid &flags,
2367 const Real bnd,
2368 const bool *axis,
2369 const ParticleDataImpl<int> *ptype,
2370 const int exclude) const
2371 {
2372 if (!part.isActive(idx) || (ptype && ((*ptype)[idx] & exclude)))
2373 return;
2374 if (axis[0])
2375 part[idx].pos.x = std::max(part[idx].pos.x, bnd);
2376 if (axis[1])
2377 part[idx].pos.x = std::min(part[idx].pos.x, static_cast<Real>(flags.getSizeX()) - bnd);
2378 if (axis[2])
2379 part[idx].pos.y = std::max(part[idx].pos.y, bnd);
2380 if (axis[3])
2381 part[idx].pos.y = std::min(part[idx].pos.y, static_cast<Real>(flags.getSizeY()) - bnd);
2382 if (flags.is3D()) {
2383 if (axis[4])
2384 part[idx].pos.z = std::max(part[idx].pos.z, bnd);
2385 if (axis[5])
2386 part[idx].pos.z = std::min(part[idx].pos.z, static_cast<Real>(flags.getSizeZ()) - bnd);
2387 }
2388 }
getArg0KnProjectOutOfBnd2389 inline ParticleSystem<S> &getArg0()
2390 {
2391 return part;
2392 }
2393 typedef ParticleSystem<S> type0;
getArg1KnProjectOutOfBnd2394 inline const FlagGrid &getArg1()
2395 {
2396 return flags;
2397 }
2398 typedef FlagGrid type1;
getArg2KnProjectOutOfBnd2399 inline const Real &getArg2()
2400 {
2401 return bnd;
2402 }
2403 typedef Real type2;
getArg3KnProjectOutOfBnd2404 inline const bool *getArg3()
2405 {
2406 return axis;
2407 }
2408 typedef bool type3;
getArg4KnProjectOutOfBnd2409 inline const ParticleDataImpl<int> *getArg4()
2410 {
2411 return ptype;
2412 }
2413 typedef ParticleDataImpl<int> type4;
getArg5KnProjectOutOfBnd2414 inline const int &getArg5()
2415 {
2416 return exclude;
2417 }
2418 typedef int type5;
runMessageKnProjectOutOfBnd2419 void runMessage()
2420 {
2421 debMsg("Executing kernel KnProjectOutOfBnd ", 3);
2422 debMsg("Kernel range"
2423 << " size " << size << " ",
2424 4);
2425 };
operatorKnProjectOutOfBnd2426 void operator()(const tbb::blocked_range<IndexInt> &__r) const
2427 {
2428 for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
2429 op(idx, part, flags, bnd, axis, ptype, exclude);
2430 }
runKnProjectOutOfBnd2431 void run()
2432 {
2433 tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
2434 }
2435 ParticleSystem<S> ∂
2436 const FlagGrid &flags;
2437 const Real bnd;
2438 const bool *axis;
2439 const ParticleDataImpl<int> *ptype;
2440 const int exclude;
2441 };
2442
2443 template<class S>
projectOutOfBnd(const FlagGrid & flags,const Real bnd,const std::string & plane,const ParticleDataImpl<int> * ptype,const int exclude)2444 void ParticleSystem<S>::projectOutOfBnd(const FlagGrid &flags,
2445 const Real bnd,
2446 const std::string &plane,
2447 const ParticleDataImpl<int> *ptype,
2448 const int exclude)
2449 {
2450 bool axis[6] = {false};
2451 for (std::string::const_iterator it = plane.begin(); it != plane.end(); ++it) {
2452 if (*it == 'x')
2453 axis[0] = true;
2454 if (*it == 'X')
2455 axis[1] = true;
2456 if (*it == 'y')
2457 axis[2] = true;
2458 if (*it == 'Y')
2459 axis[3] = true;
2460 if (*it == 'z')
2461 axis[4] = true;
2462 if (*it == 'Z')
2463 axis[5] = true;
2464 }
2465 KnProjectOutOfBnd<S>(*this, flags, bnd, axis, ptype, exclude);
2466 }
2467
resizeAll(IndexInt size)2468 template<class S> void ParticleSystem<S>::resizeAll(IndexInt size)
2469 {
2470 // resize all buffers to target size in 1 go
2471 mData.resize(size);
2472 for (IndexInt i = 0; i < (IndexInt)mPartData.size(); ++i)
2473 mPartData[i]->resize(size);
2474 }
2475
compress()2476 template<class S> void ParticleSystem<S>::compress()
2477 {
2478 IndexInt nextRead = mData.size();
2479 for (IndexInt i = 0; i < (IndexInt)mData.size(); i++) {
2480 while ((mData[i].flag & PDELETE) != 0) {
2481 nextRead--;
2482 mData[i] = mData[nextRead];
2483 // ugly, but prevent virtual function calls here:
2484 for (IndexInt pd = 0; pd < (IndexInt)mPdataReal.size(); ++pd)
2485 mPdataReal[pd]->copyValue(nextRead, i);
2486 for (IndexInt pd = 0; pd < (IndexInt)mPdataVec3.size(); ++pd)
2487 mPdataVec3[pd]->copyValue(nextRead, i);
2488 for (IndexInt pd = 0; pd < (IndexInt)mPdataInt.size(); ++pd)
2489 mPdataInt[pd]->copyValue(nextRead, i);
2490 mData[nextRead].flag = PINVALID;
2491 }
2492 }
2493 if (nextRead < (IndexInt)mData.size())
2494 debMsg("Deleted " << ((IndexInt)mData.size() - nextRead) << " particles", 1); // debug info
2495
2496 resizeAll(nextRead);
2497 mDeletes = 0;
2498 mDeleteChunk = mData.size() / DELETE_PART;
2499 }
2500
2501 //! insert buffered positions as new particles, update additional particle data
insertBufferedParticles()2502 template<class S> void ParticleSystem<S>::insertBufferedParticles()
2503 {
2504 // clear new flag everywhere
2505 for (IndexInt i = 0; i < (IndexInt)mData.size(); ++i)
2506 mData[i].flag &= ~PNEW;
2507
2508 if (mNewBufferPos.empty())
2509 return;
2510 IndexInt bufferSize = mNewBufferPos.size();
2511 IndexInt partsSize = mData.size();
2512
2513 if (mMaxParticles > 0)
2514 assertMsg(mMaxParticles >= partsSize,
2515 "Particle system cannot contain more particles that the maximum allowed number");
2516
2517 // max number of new particles that can be inserted, adjusted buffer size when using maxParticles
2518 // field
2519 IndexInt numNewParts = (mMaxParticles > 0) ? mMaxParticles - mData.size() : bufferSize;
2520 if (numNewParts > bufferSize)
2521 numNewParts = bufferSize; // upper clamp
2522
2523 assertMsg(numNewParts >= 0, "Must not have negative number of new particles");
2524
2525 // new size of particle system
2526 IndexInt newSize = mData.size() + numNewParts;
2527 if (mMaxParticles > 0)
2528 assertMsg(newSize <= mMaxParticles,
2529 "Particle system cannot contain more particles that the maximum allowed number");
2530 resizeAll(newSize);
2531
2532 int insertFlag;
2533 Vec3 insertPos;
2534 static RandomStream mRand(9832);
2535 for (IndexInt i = 0; i < numNewParts; ++i) {
2536
2537 // get random index in newBuffer vector
2538 // we are inserting particles randomly so that they are sampled uniformly in the fluid region
2539 // otherwise, regions of fluid can remain completely empty once mData.size() == maxParticles is
2540 // reached.
2541 int randIndex = floor(mRand.getReal() * mNewBufferPos.size());
2542
2543 // get elements from new buffers with random index
2544 std::swap(mNewBufferPos[randIndex], mNewBufferPos.back());
2545 insertPos = mNewBufferPos.back();
2546 mNewBufferPos.pop_back();
2547
2548 insertFlag = 0;
2549 if (!mNewBufferFlag.empty()) {
2550 std::swap(mNewBufferFlag[randIndex], mNewBufferFlag.back());
2551 insertFlag = mNewBufferFlag.back();
2552 mNewBufferFlag.pop_back();
2553 }
2554
2555 mData[partsSize].pos = insertPos;
2556 mData[partsSize].flag = PNEW | insertFlag;
2557
2558 // now init pdata fields from associated grids...
2559 for (IndexInt pd = 0; pd < (IndexInt)mPdataReal.size(); ++pd)
2560 mPdataReal[pd]->initNewValue(partsSize, insertPos);
2561 for (IndexInt pd = 0; pd < (IndexInt)mPdataVec3.size(); ++pd)
2562 mPdataVec3[pd]->initNewValue(partsSize, insertPos);
2563 for (IndexInt pd = 0; pd < (IndexInt)mPdataInt.size(); ++pd)
2564 mPdataInt[pd]->initNewValue(partsSize, insertPos);
2565 partsSize++;
2566 }
2567 debMsg("Added & initialized " << numNewParts << " particles", 2); // debug info
2568 mNewBufferPos.clear();
2569 mNewBufferFlag.clear();
2570 }
2571
compress()2572 template<class DATA, class CON> void ConnectedParticleSystem<DATA, CON>::compress()
2573 {
2574 const IndexInt sz = ParticleSystem<DATA>::size();
2575 IndexInt *renumber_back = new IndexInt[sz];
2576 IndexInt *renumber = new IndexInt[sz];
2577 for (IndexInt i = 0; i < sz; i++)
2578 renumber[i] = renumber_back[i] = -1;
2579
2580 // reorder elements
2581 std::vector<DATA> &data = ParticleSystem<DATA>::mData;
2582 IndexInt nextRead = sz;
2583 for (IndexInt i = 0; i < nextRead; i++) {
2584 if ((data[i].flag & ParticleBase::PDELETE) != 0) {
2585 nextRead--;
2586 data[i] = data[nextRead];
2587 data[nextRead].flag = 0;
2588 renumber_back[i] = nextRead;
2589 }
2590 else
2591 renumber_back[i] = i;
2592 }
2593
2594 // acceleration structure
2595 for (IndexInt i = 0; i < nextRead; i++)
2596 renumber[renumber_back[i]] = i;
2597
2598 // rename indices in filaments
2599 for (IndexInt i = 0; i < (IndexInt)mSegments.size(); i++)
2600 mSegments[i].renumber(renumber);
2601
2602 ParticleSystem<DATA>::mData.resize(nextRead);
2603 ParticleSystem<DATA>::mDeletes = 0;
2604 ParticleSystem<DATA>::mDeleteChunk = ParticleSystem<DATA>::size() / DELETE_PART;
2605
2606 delete[] renumber;
2607 delete[] renumber_back;
2608 }
2609
clone()2610 template<class S> ParticleBase *ParticleSystem<S>::clone()
2611 {
2612 ParticleSystem<S> *nm = new ParticleSystem<S>(getParent());
2613 if (this->mAllowCompress)
2614 compress();
2615
2616 nm->mData = mData;
2617 nm->setName(getName());
2618 this->cloneParticleData(nm);
2619 return nm;
2620 }
2621
clone()2622 template<class DATA, class CON> ParticleBase *ConnectedParticleSystem<DATA, CON>::clone()
2623 {
2624 ConnectedParticleSystem<DATA, CON> *nm = new ConnectedParticleSystem<DATA, CON>(
2625 this->getParent());
2626 if (this->mAllowCompress)
2627 compress();
2628
2629 nm->mData = this->mData;
2630 nm->mSegments = mSegments;
2631 nm->setName(this->getName());
2632 this->cloneParticleData(nm);
2633 return nm;
2634 }
2635
infoString()2636 template<class S> std::string ParticleSystem<S>::infoString() const
2637 {
2638 std::stringstream s;
2639 s << "ParticleSys '" << getName() << "'\n-> ";
2640 if (this->getNumPdata() > 0)
2641 s << "pdata: " << this->getNumPdata();
2642 s << "parts: " << size();
2643 // for(IndexInt i=0; i<(IndexInt)mPartData.size(); ++i) { sstr << i<<":" << mPartData[i]->size()
2644 // <<" "; }
2645 return s.str();
2646 }
2647
checkPartIndex(IndexInt idx)2648 template<class S> inline void ParticleSystem<S>::checkPartIndex(IndexInt idx) const
2649 {
2650 IndexInt mySize = this->size();
2651 if (idx < 0 || idx > mySize) {
2652 errMsg("ParticleBase "
2653 << " size " << mySize << " : index " << idx << " out of bound ");
2654 }
2655 }
2656
checkPartIndex(IndexInt idx)2657 inline void ParticleDataBase::checkPartIndex(IndexInt idx) const
2658 {
2659 IndexInt mySize = this->getSizeSlow();
2660 if (idx < 0 || idx > mySize) {
2661 errMsg("ParticleData "
2662 << " size " << mySize << " : index " << idx << " out of bound ");
2663 }
2664 if (mpParticleSys && mpParticleSys->getSizeSlow() != mySize) {
2665 errMsg("ParticleData "
2666 << " size " << mySize << " does not match parent! (" << mpParticleSys->getSizeSlow()
2667 << ") ");
2668 }
2669 }
2670
2671 // set contents to zero, as for a grid
clear()2672 template<class T> void ParticleDataImpl<T>::clear()
2673 {
2674 for (IndexInt i = 0; i < (IndexInt)mData.size(); ++i)
2675 mData[i] = 0.;
2676 }
2677
2678 //! count by type flag
2679 int countParticles(const ParticleDataImpl<int> &t, const int flag);
2680
2681 } // namespace Manta
2682
2683 #endif
2684