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> &copyFrom(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> &part;
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> &part;
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