tornavis/extern/mantaflow/preprocessed/particle.h

2706 lines
83 KiB
C++

// DO NOT EDIT !
// This file is generated using the MantaFlow preprocessor (prep generate).
/******************************************************************************
*
* MantaFlow fluid solver framework
* Copyright 2011 Tobias Pfaff, Nils Thuerey
*
* This program is free software, distributed under the terms of the
* Apache License, Version 2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Base class for particle systems
*
******************************************************************************/
#ifndef _PARTICLE_H
#define _PARTICLE_H
#include <vector>
#include "grid.h"
#include "vectorbase.h"
#include "integrator.h"
#include "randomstream.h"
namespace Manta {
// fwd decl
template<class T> class Grid;
class ParticleDataBase;
template<class T> class ParticleDataImpl;
//! Baseclass for particle systems. Does not implement any data
class ParticleBase : public PbClass {
public:
enum SystemType { BASE = 0, PARTICLE, VORTEX, FILAMENT, FLIP, TURBULENCE, INDEX };
enum ParticleStatus {
PNONE = 0,
PNEW = (1 << 0), // particles newly created in this step
PSPRAY = (1 << 1), // secondary particle types
PBUBBLE = (1 << 2),
PFOAM = (1 << 3),
PTRACER = (1 << 4),
PDELETE = (1 << 10), // mark as deleted, will be deleted in next compress() step
PINVALID = (1 << 30), // unused
};
ParticleBase(FluidSolver *parent, int fixedSeed = -1);
static int _W_0(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
PbClass *obj = Pb::objFromPy(_self);
if (obj)
delete obj;
try {
PbArgs _args(_linargs, _kwds);
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(0, "ParticleBase::ParticleBase", !noTiming);
{
ArgLocker _lock;
FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
int fixedSeed = _args.getOpt<int>("fixedSeed", 1, -1, &_lock);
obj = new ParticleBase(parent, fixedSeed);
obj->registerObject(_self, &_args);
_args.check();
}
pbFinalizePlugin(obj->getParent(), "ParticleBase::ParticleBase", !noTiming);
return 0;
}
catch (std::exception &e) {
pbSetError("ParticleBase::ParticleBase", e.what());
return -1;
}
}
virtual ~ParticleBase();
//! copy all the particle data thats registered with the other particle system to this one
virtual void cloneParticleData(ParticleBase *nm);
virtual SystemType getType() const
{
return BASE;
}
virtual std::string infoString() const;
virtual ParticleBase *clone()
{
assertMsg(false, "Dont use, override...");
return nullptr;
}
//! slow virtual function to query size, do not use in kernels! use size() instead
virtual IndexInt getSizeSlow() const
{
assertMsg(false, "Dont use, override...");
return 0;
}
//! add a position as potential candidate for new particle (todo, make usable from parallel
//! threads)
inline void addBuffered(const Vec3 &pos, int flag = 0);
virtual void resize(IndexInt size)
{
assertMsg(false, "Dont use, override...");
return;
}
virtual void resizeAll(IndexInt size)
{
assertMsg(false, "Dont use, override...");
return;
}
inline int getSeed()
{
return mSeed;
}
//! particle data functions
//! create a particle data object
PbClass *create(PbType type, PbTypeVec T = PbTypeVec(), const std::string &name = "");
static PyObject *_W_1(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleBase *pbo = dynamic_cast<ParticleBase *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleBase::create", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
PbType type = _args.get<PbType>("type", 0, &_lock);
PbTypeVec T = _args.getOpt<PbTypeVec>("T", 1, PbTypeVec(), &_lock);
const std::string &name = _args.getOpt<std::string>("name", 2, "", &_lock);
pbo->_args.copy(_args);
_retval = toPy(pbo->create(type, T, name));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleBase::create", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleBase::create", e.what());
return 0;
}
}
//! add a particle data field, set its parent particle-system pointer
void registerPdata(ParticleDataBase *pdata);
void registerPdataReal(ParticleDataImpl<Real> *pdata);
void registerPdataVec3(ParticleDataImpl<Vec3> *pdata);
void registerPdataInt(ParticleDataImpl<int> *pdata);
//! remove a particle data entry
void deregister(ParticleDataBase *pdata);
//! add one zero entry to all data fields
void addAllPdata();
// note - deletion of pdata is handled in compress function
//! how many are there?
IndexInt getNumPdata() const
{
return mPartData.size();
}
//! access one of the fields
ParticleDataBase *getPdata(int i)
{
return mPartData[i];
}
//! expose maximum number of particles to python
int mMaxParticles;
static PyObject *_GET_mMaxParticles(PyObject *self, void *cl)
{
ParticleBase *pbo = dynamic_cast<ParticleBase *>(Pb::objFromPy(self));
return toPy(pbo->mMaxParticles);
}
static int _SET_mMaxParticles(PyObject *self, PyObject *val, void *cl)
{
ParticleBase *pbo = dynamic_cast<ParticleBase *>(Pb::objFromPy(self));
pbo->mMaxParticles = fromPy<int>(val);
return 0;
}
protected:
//! new particle candidates
std::vector<Vec3> mNewBufferPos;
std::vector<int> mNewBufferFlag;
//! allow automatic compression / resize? disallowed for, eg, flip particle systems
bool mAllowCompress;
//! store particle data , each pointer has its own storage vector of a certain type (int, real,
//! vec3)
std::vector<ParticleDataBase *> mPartData;
//! lists of different types, for fast operations w/o virtual function calls (all calls necessary
//! per particle)
std::vector<ParticleDataImpl<Real> *> mPdataReal;
std::vector<ParticleDataImpl<Vec3> *> mPdataVec3;
std::vector<ParticleDataImpl<int> *> mPdataInt;
//! indicate that pdata of this particle system is copied, and needs to be freed
bool mFreePdata;
//! custom seed for particle systems, used by plugins
int mSeed; //! fix global random seed storage, used mainly by functions in this class
static int globalSeed;
public:
PbArgs _args;
}
#define _C_ParticleBase
;
//! Main class for particle systems
/*! Basetype S must at least contain flag, pos fields */
template<class S> class ParticleSystem : public ParticleBase {
public:
ParticleSystem(FluidSolver *parent) : ParticleBase(parent), mDeletes(0), mDeleteChunk(0)
{
}
static int _W_2(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
PbClass *obj = Pb::objFromPy(_self);
if (obj)
delete obj;
try {
PbArgs _args(_linargs, _kwds);
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(0, "ParticleSystem::ParticleSystem", !noTiming);
{
ArgLocker _lock;
FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
obj = new ParticleSystem(parent);
obj->registerObject(_self, &_args);
_args.check();
}
pbFinalizePlugin(obj->getParent(), "ParticleSystem::ParticleSystem", !noTiming);
return 0;
}
catch (std::exception &e) {
pbSetError("ParticleSystem::ParticleSystem", e.what());
return -1;
}
}
virtual ~ParticleSystem(){};
virtual SystemType getType() const
{
return S::getType();
};
//! accessors
inline S &operator[](IndexInt idx)
{
DEBUG_ONLY(checkPartIndex(idx));
return mData[idx];
}
inline const S &operator[](IndexInt idx) const
{
DEBUG_ONLY(checkPartIndex(idx));
return mData[idx];
}
//! return size of container
//! note , python binding disabled for now! cannot yet deal with long-long types
inline IndexInt size() const
{
return mData.size();
}
//! slow virtual function of base class, also returns size
virtual IndexInt getSizeSlow() const
{
return size();
}
//! note , special call for python, note - doesnt support more than 2b parts!
int pySize() const
{
return (int)mData.size();
}
static PyObject *_W_3(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleSystem::pySize", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
pbo->_args.copy(_args);
_retval = toPy(pbo->pySize());
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleSystem::pySize", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleSystem::pySize", e.what());
return 0;
}
}
//! query status
inline int getStatus(IndexInt idx) const
{
DEBUG_ONLY(checkPartIndex(idx));
return mData[idx].flag;
}
inline bool isActive(IndexInt idx) const
{
DEBUG_ONLY(checkPartIndex(idx));
return (mData[idx].flag & PDELETE) == 0;
}
inline bool isSpray(IndexInt idx) const
{
DEBUG_ONLY(checkPartIndex(idx));
return (mData[idx].flag & PSPRAY);
}
inline bool isBubble(IndexInt idx) const
{
DEBUG_ONLY(checkPartIndex(idx));
return (mData[idx].flag & PBUBBLE);
}
inline bool isFoam(IndexInt idx) const
{
DEBUG_ONLY(checkPartIndex(idx));
return (mData[idx].flag & PFOAM);
}
inline bool isTracer(IndexInt idx) const
{
DEBUG_ONLY(checkPartIndex(idx));
return (mData[idx].flag & PTRACER);
}
//! update status
inline void setStatus(IndexInt idx, const int status)
{
DEBUG_ONLY(checkPartIndex(idx));
mData[idx].flag = status;
}
//! safe accessor for python
void setPos(const IndexInt idx, const Vec3 &pos)
{
DEBUG_ONLY(checkPartIndex(idx));
mData[idx].pos = pos;
}
static PyObject *_W_4(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleSystem::setPos", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const IndexInt idx = _args.get<IndexInt>("idx", 0, &_lock);
const Vec3 &pos = _args.get<Vec3>("pos", 1, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->setPos(idx, pos);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleSystem::setPos", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleSystem::setPos", e.what());
return 0;
}
}
const Vec3 &getPos(const IndexInt idx) const
{
DEBUG_ONLY(checkPartIndex(idx));
return mData[idx].pos;
}
static PyObject *_W_5(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleSystem::getPos", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const IndexInt idx = _args.get<IndexInt>("idx", 0, &_lock);
pbo->_args.copy(_args);
_retval = toPy(pbo->getPos(idx));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleSystem::getPos", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleSystem::getPos", e.what());
return 0;
}
}
//! copy all positions into pdata vec3 field
void getPosPdata(ParticleDataImpl<Vec3> &target) const;
static PyObject *_W_6(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleSystem::getPosPdata", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
ParticleDataImpl<Vec3> &target = *_args.getPtr<ParticleDataImpl<Vec3>>(
"target", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->getPosPdata(target);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleSystem::getPosPdata", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleSystem::getPosPdata", e.what());
return 0;
}
}
void setPosPdata(const ParticleDataImpl<Vec3> &source);
static PyObject *_W_7(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleSystem::setPosPdata", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const ParticleDataImpl<Vec3> &source = *_args.getPtr<ParticleDataImpl<Vec3>>(
"source", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->setPosPdata(source);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleSystem::setPosPdata", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleSystem::setPosPdata", e.what());
return 0;
}
}
//! transform coordinate system from one grid size to another (usually upon load)
void transformPositions(Vec3i dimOld, Vec3i dimNew);
//! explicitly trigger compression from outside
void doCompress()
{
if (mDeletes > mDeleteChunk)
compress();
}
//! insert buffered positions as new particles, update additional particle data
void insertBufferedParticles();
//! resize only the data vector, only use if you know what you're doing, otherwise use
//! resizeAll()
virtual void resize(IndexInt size)
{
mData.resize(size);
}
//! resize data vector, and all pdata fields
virtual void resizeAll(IndexInt size);
//! adding and deleting
inline void kill(IndexInt idx);
IndexInt add(const S &data);
//! remove all particles, init 0 length arrays (also pdata)
void clear();
static PyObject *_W_8(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleSystem::clear", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->clear();
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleSystem::clear", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleSystem::clear", e.what());
return 0;
}
}
//! Advect particle in grid velocity field
void advectInGrid(const FlagGrid &flags,
const MACGrid &vel,
const int integrationMode,
const bool deleteInObstacle = true,
const bool stopInObstacle = true,
const bool skipNew = false,
const ParticleDataImpl<int> *ptype = nullptr,
const int exclude = 0);
static PyObject *_W_9(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleSystem::advectInGrid", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
const MACGrid &vel = *_args.getPtr<MACGrid>("vel", 1, &_lock);
const int integrationMode = _args.get<int>("integrationMode", 2, &_lock);
const bool deleteInObstacle = _args.getOpt<bool>("deleteInObstacle", 3, true, &_lock);
const bool stopInObstacle = _args.getOpt<bool>("stopInObstacle", 4, true, &_lock);
const bool skipNew = _args.getOpt<bool>("skipNew", 5, false, &_lock);
const ParticleDataImpl<int> *ptype = _args.getPtrOpt<ParticleDataImpl<int>>(
"ptype", 6, nullptr, &_lock);
const int exclude = _args.getOpt<int>("exclude", 7, 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->advectInGrid(flags,
vel,
integrationMode,
deleteInObstacle,
stopInObstacle,
skipNew,
ptype,
exclude);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleSystem::advectInGrid", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleSystem::advectInGrid", e.what());
return 0;
}
}
//! Project particles outside obstacles
void projectOutside(Grid<Vec3> &gradient);
static PyObject *_W_10(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleSystem::projectOutside", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
Grid<Vec3> &gradient = *_args.getPtr<Grid<Vec3>>("gradient", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->projectOutside(gradient);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleSystem::projectOutside", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleSystem::projectOutside", e.what());
return 0;
}
}
void projectOutOfBnd(const FlagGrid &flags,
const Real bnd,
const std::string &plane = "xXyYzZ",
const ParticleDataImpl<int> *ptype = nullptr,
const int exclude = 0);
static PyObject *_W_11(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleSystem *pbo = dynamic_cast<ParticleSystem *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleSystem::projectOutOfBnd", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
const Real bnd = _args.get<Real>("bnd", 1, &_lock);
const std::string &plane = _args.getOpt<std::string>("plane", 2, "xXyYzZ", &_lock);
const ParticleDataImpl<int> *ptype = _args.getPtrOpt<ParticleDataImpl<int>>(
"ptype", 3, nullptr, &_lock);
const int exclude = _args.getOpt<int>("exclude", 4, 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->projectOutOfBnd(flags, bnd, plane, ptype, exclude);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleSystem::projectOutOfBnd", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleSystem::projectOutOfBnd", e.what());
return 0;
}
}
virtual ParticleBase *clone();
virtual std::string infoString() const;
//! debugging
inline void checkPartIndex(IndexInt idx) const;
protected:
//! deletion count , and interval for re-compressing
IndexInt mDeletes, mDeleteChunk;
//! the particle data
std::vector<S> mData;
//! reduce storage , called by doCompress
virtual void compress();
public:
PbArgs _args;
}
#define _C_ParticleSystem
;
//******************************************************************************
//! Simplest data class for particle systems
//! contains a position and an int flag; note that these are deprectated, and will at
//! some point be replaced by the more flexible pdata fields. For now manually copy with
//! getPosPdata / setPosPdata.
struct BasicParticleData {
public:
BasicParticleData() : pos(0.), flag(0)
{
}
BasicParticleData(const Vec3 &p) : pos(p), flag(0)
{
}
static ParticleBase::SystemType getType()
{
return ParticleBase::PARTICLE;
}
//! data (note, this size is currently hard coded for uni i/o)
Vec3 pos;
int flag;
};
class BasicParticleSystem : public ParticleSystem<BasicParticleData> {
public:
BasicParticleSystem(FluidSolver *parent);
static int _W_12(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
PbClass *obj = Pb::objFromPy(_self);
if (obj)
delete obj;
try {
PbArgs _args(_linargs, _kwds);
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(0, "BasicParticleSystem::BasicParticleSystem", !noTiming);
{
ArgLocker _lock;
FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
obj = new BasicParticleSystem(parent);
obj->registerObject(_self, &_args);
_args.check();
}
pbFinalizePlugin(obj->getParent(), "BasicParticleSystem::BasicParticleSystem", !noTiming);
return 0;
}
catch (std::exception &e) {
pbSetError("BasicParticleSystem::BasicParticleSystem", e.what());
return -1;
}
}
//! file io
int save(const std::string name);
static PyObject *_W_13(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
BasicParticleSystem *pbo = dynamic_cast<BasicParticleSystem *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "BasicParticleSystem::save", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const std::string name = _args.get<std::string>("name", 0, &_lock);
pbo->_args.copy(_args);
_retval = toPy(pbo->save(name));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "BasicParticleSystem::save", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("BasicParticleSystem::save", e.what());
return 0;
}
}
int load(const std::string name);
static PyObject *_W_14(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
BasicParticleSystem *pbo = dynamic_cast<BasicParticleSystem *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "BasicParticleSystem::load", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const std::string name = _args.get<std::string>("name", 0, &_lock);
pbo->_args.copy(_args);
_retval = toPy(pbo->load(name));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "BasicParticleSystem::load", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("BasicParticleSystem::load", e.what());
return 0;
}
}
//! save to text file
void writeParticlesText(const std::string name) const;
//! other output formats
void writeParticlesRawPositionsGz(const std::string name) const;
void writeParticlesRawVelocityGz(const std::string name) const;
//! read from other particle system (with resize)
void readParticles(BasicParticleSystem *from);
static PyObject *_W_15(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
BasicParticleSystem *pbo = dynamic_cast<BasicParticleSystem *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "BasicParticleSystem::readParticles", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
BasicParticleSystem *from = _args.getPtr<BasicParticleSystem>("from", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->readParticles(from);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "BasicParticleSystem::readParticles", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("BasicParticleSystem::readParticles", e.what());
return 0;
}
}
//! add particles in python
void addParticle(Vec3 pos)
{
add(BasicParticleData(pos));
}
static PyObject *_W_16(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
BasicParticleSystem *pbo = dynamic_cast<BasicParticleSystem *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "BasicParticleSystem::addParticle", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
Vec3 pos = _args.get<Vec3>("pos", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->addParticle(pos);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "BasicParticleSystem::addParticle", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("BasicParticleSystem::addParticle", e.what());
return 0;
}
}
//! dangerous, get low level access - avoid usage, only used in vortex filament advection for now
std::vector<BasicParticleData> &getData()
{
return mData;
}
void printParts(IndexInt start = -1, IndexInt stop = -1, bool printIndex = false);
static PyObject *_W_17(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
BasicParticleSystem *pbo = dynamic_cast<BasicParticleSystem *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "BasicParticleSystem::printParts", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
IndexInt start = _args.getOpt<IndexInt>("start", 0, -1, &_lock);
IndexInt stop = _args.getOpt<IndexInt>("stop", 1, -1, &_lock);
bool printIndex = _args.getOpt<bool>("printIndex", 2, false, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->printParts(start, stop, printIndex);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "BasicParticleSystem::printParts", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("BasicParticleSystem::printParts", e.what());
return 0;
}
}
//! get data pointer of particle data
std::string getDataPointer();
static PyObject *_W_18(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
BasicParticleSystem *pbo = dynamic_cast<BasicParticleSystem *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "BasicParticleSystem::getDataPointer", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
pbo->_args.copy(_args);
_retval = toPy(pbo->getDataPointer());
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "BasicParticleSystem::getDataPointer", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("BasicParticleSystem::getDataPointer", e.what());
return 0;
}
}
public:
PbArgs _args;
}
#define _C_BasicParticleSystem
;
//******************************************************************************
//! Index into other particle system
// used for grid based neighborhood searches on generic particle systems (stores
// only active particles, and reduces copied data)
// note - pos & flag are disabled here, do not use!
struct ParticleIndexData {
public:
ParticleIndexData() : sourceIndex(0)
{
}
static ParticleBase::SystemType getType()
{
return ParticleBase::INDEX;
}
IndexInt sourceIndex; // index of this particle in the original particle system
//! note - the following two are needed for template instantiation, but not used
//! for the particle index system (use values from original one!)
static Vec3 pos; // do not use...
static int flag; // not needed usally
// Vec3 pos; // enable for debugging
};
class ParticleIndexSystem : public ParticleSystem<ParticleIndexData> {
public:
ParticleIndexSystem(FluidSolver *parent) : ParticleSystem<ParticleIndexData>(parent)
{
}
static int _W_19(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
PbClass *obj = Pb::objFromPy(_self);
if (obj)
delete obj;
try {
PbArgs _args(_linargs, _kwds);
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(0, "ParticleIndexSystem::ParticleIndexSystem", !noTiming);
{
ArgLocker _lock;
FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
obj = new ParticleIndexSystem(parent);
obj->registerObject(_self, &_args);
_args.check();
}
pbFinalizePlugin(obj->getParent(), "ParticleIndexSystem::ParticleIndexSystem", !noTiming);
return 0;
}
catch (std::exception &e) {
pbSetError("ParticleIndexSystem::ParticleIndexSystem", e.what());
return -1;
}
};
public:
PbArgs _args;
}
#define _C_ParticleIndexSystem
;
//******************************************************************************
//! Particle set with connectivity
template<class DATA, class CON> class ConnectedParticleSystem : public ParticleSystem<DATA> {
public:
ConnectedParticleSystem(FluidSolver *parent) : ParticleSystem<DATA>(parent)
{
}
static int _W_20(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
PbClass *obj = Pb::objFromPy(_self);
if (obj)
delete obj;
try {
PbArgs _args(_linargs, _kwds);
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(0, "ConnectedParticleSystem::ConnectedParticleSystem", !noTiming);
{
ArgLocker _lock;
FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
obj = new ConnectedParticleSystem(parent);
obj->registerObject(_self, &_args);
_args.check();
}
pbFinalizePlugin(
obj->getParent(), "ConnectedParticleSystem::ConnectedParticleSystem", !noTiming);
return 0;
}
catch (std::exception &e) {
pbSetError("ConnectedParticleSystem::ConnectedParticleSystem", e.what());
return -1;
}
}
//! accessors
inline bool isSegActive(int i)
{
return (mSegments[i].flag & ParticleBase::PDELETE) == 0;
}
inline int segSize() const
{
return mSegments.size();
}
inline CON &seg(int i)
{
return mSegments[i];
}
inline const CON &seg(int i) const
{
return mSegments[i];
}
virtual ParticleBase *clone();
protected:
std::vector<CON> mSegments;
virtual void compress();
public:
PbArgs _args;
}
#define _C_ConnectedParticleSystem
;
//******************************************************************************
//! abstract interface for particle data
class ParticleDataBase : public PbClass {
public:
ParticleDataBase(FluidSolver *parent);
static int _W_21(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
PbClass *obj = Pb::objFromPy(_self);
if (obj)
delete obj;
try {
PbArgs _args(_linargs, _kwds);
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(0, "ParticleDataBase::ParticleDataBase", !noTiming);
{
ArgLocker _lock;
FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
obj = new ParticleDataBase(parent);
obj->registerObject(_self, &_args);
_args.check();
}
pbFinalizePlugin(obj->getParent(), "ParticleDataBase::ParticleDataBase", !noTiming);
return 0;
}
catch (std::exception &e) {
pbSetError("ParticleDataBase::ParticleDataBase", e.what());
return -1;
}
}
virtual ~ParticleDataBase();
//! data type IDs, in line with those for grids
enum PdataType { TypeNone = 0, TypeReal = 1, TypeInt = 2, TypeVec3 = 4 };
//! interface functions, using assert instead of pure virtual for python compatibility
virtual IndexInt getSizeSlow() const
{
assertMsg(false, "Dont use, override...");
return 0;
}
virtual void addEntry()
{
assertMsg(false, "Dont use, override...");
return;
}
virtual ParticleDataBase *clone()
{
assertMsg(false, "Dont use, override...");
return nullptr;
}
virtual PdataType getType() const
{
assertMsg(false, "Dont use, override...");
return TypeNone;
}
virtual void resize(IndexInt size)
{
assertMsg(false, "Dont use, override...");
return;
}
virtual void copyValueSlow(IndexInt from, IndexInt to)
{
assertMsg(false, "Dont use, override...");
return;
}
//! set / get base pointer to parent particle system
void setParticleSys(ParticleBase *set)
{
mpParticleSys = set;
}
ParticleBase *getParticleSys()
{
return mpParticleSys;
}
//! debugging
inline void checkPartIndex(IndexInt idx) const;
protected:
ParticleBase *mpParticleSys;
public:
PbArgs _args;
}
#define _C_ParticleDataBase
;
//! abstract interface for particle data
template<class T> class ParticleDataImpl : public ParticleDataBase {
public:
ParticleDataImpl(FluidSolver *parent);
static int _W_22(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
PbClass *obj = Pb::objFromPy(_self);
if (obj)
delete obj;
try {
PbArgs _args(_linargs, _kwds);
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(0, "ParticleDataImpl::ParticleDataImpl", !noTiming);
{
ArgLocker _lock;
FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
obj = new ParticleDataImpl(parent);
obj->registerObject(_self, &_args);
_args.check();
}
pbFinalizePlugin(obj->getParent(), "ParticleDataImpl::ParticleDataImpl", !noTiming);
return 0;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::ParticleDataImpl", e.what());
return -1;
}
}
ParticleDataImpl(FluidSolver *parent, ParticleDataImpl<T> *other);
virtual ~ParticleDataImpl();
//! access data
inline T &get(const IndexInt idx)
{
DEBUG_ONLY(checkPartIndex(idx));
return mData[idx];
}
inline const T &get(const IndexInt idx) const
{
DEBUG_ONLY(checkPartIndex(idx));
return mData[idx];
}
inline T &operator[](const IndexInt idx)
{
DEBUG_ONLY(checkPartIndex(idx));
return mData[idx];
}
inline const T &operator[](const IndexInt idx) const
{
DEBUG_ONLY(checkPartIndex(idx));
return mData[idx];
}
//! set data
inline void set(const IndexInt idx, T &val)
{
DEBUG_ONLY(checkPartIndex(idx));
mData[idx] = val;
}
//! set all values to 0, note - different from particleSystem::clear! doesnt modify size of array
//! (has to stay in sync with parent system)
void clear();
static PyObject *_W_23(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::clear", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->clear();
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::clear", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::clear", e.what());
return 0;
}
}
//! set grid from which to get data...
void setSource(Grid<T> *grid, bool isMAC = false);
static PyObject *_W_24(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::setSource", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
Grid<T> *grid = _args.getPtr<Grid<T>>("grid", 0, &_lock);
bool isMAC = _args.getOpt<bool>("isMAC", 1, false, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->setSource(grid, isMAC);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::setSource", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::setSource", e.what());
return 0;
}
}
//! particle data base interface
virtual IndexInt getSizeSlow() const;
virtual void addEntry();
virtual ParticleDataBase *clone();
virtual PdataType getType() const;
virtual void resize(IndexInt s);
virtual void copyValueSlow(IndexInt from, IndexInt to);
IndexInt size() const
{
return mData.size();
}
//! fast inlined functions for per particle operations
inline void copyValue(IndexInt from, IndexInt to)
{
get(to) = get(from);
}
void initNewValue(IndexInt idx, Vec3 pos);
//! python interface (similar to grid data)
ParticleDataImpl<T> &copyFrom(const ParticleDataImpl<T> &a);
static PyObject *_W_25(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::copyFrom", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const ParticleDataImpl<T> &a = *_args.getPtr<ParticleDataImpl<T>>("a", 0, &_lock);
pbo->_args.copy(_args);
_retval = toPy(pbo->copyFrom(a));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::copyFrom", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::copyFrom", e.what());
return 0;
}
}
void setConst(const T &s);
static PyObject *_W_26(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::setConst", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const T &s = *_args.getPtr<T>("s", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->setConst(s);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::setConst", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::setConst", e.what());
return 0;
}
}
void setConstRange(const T &s, const int begin, const int end);
static PyObject *_W_27(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::setConstRange", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const T &s = *_args.getPtr<T>("s", 0, &_lock);
const int begin = _args.get<int>("begin", 1, &_lock);
const int end = _args.get<int>("end", 2, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->setConstRange(s, begin, end);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::setConstRange", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::setConstRange", e.what());
return 0;
}
}
void add(const ParticleDataImpl<T> &a);
static PyObject *_W_28(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::add", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const ParticleDataImpl<T> &a = *_args.getPtr<ParticleDataImpl<T>>("a", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->add(a);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::add", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::add", e.what());
return 0;
}
}
void sub(const ParticleDataImpl<T> &a);
static PyObject *_W_29(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::sub", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const ParticleDataImpl<T> &a = *_args.getPtr<ParticleDataImpl<T>>("a", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->sub(a);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::sub", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::sub", e.what());
return 0;
}
}
void addConst(const T &s);
static PyObject *_W_30(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::addConst", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const T &s = *_args.getPtr<T>("s", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->addConst(s);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::addConst", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::addConst", e.what());
return 0;
}
}
void addScaled(const ParticleDataImpl<T> &a, const T &factor);
static PyObject *_W_31(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::addScaled", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const ParticleDataImpl<T> &a = *_args.getPtr<ParticleDataImpl<T>>("a", 0, &_lock);
const T &factor = *_args.getPtr<T>("factor", 1, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->addScaled(a, factor);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::addScaled", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::addScaled", e.what());
return 0;
}
}
void mult(const ParticleDataImpl<T> &a);
static PyObject *_W_32(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::mult", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const ParticleDataImpl<T> &a = *_args.getPtr<ParticleDataImpl<T>>("a", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->mult(a);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::mult", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::mult", e.what());
return 0;
}
}
void multConst(const T &s);
static PyObject *_W_33(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::multConst", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const T &s = *_args.getPtr<T>("s", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->multConst(s);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::multConst", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::multConst", e.what());
return 0;
}
}
void safeDiv(const ParticleDataImpl<T> &a);
static PyObject *_W_34(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::safeDiv", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const ParticleDataImpl<T> &a = *_args.getPtr<ParticleDataImpl<T>>("a", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->safeDiv(a);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::safeDiv", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::safeDiv", e.what());
return 0;
}
}
void clamp(const Real vmin, const Real vmax);
static PyObject *_W_35(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::clamp", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const Real vmin = _args.get<Real>("vmin", 0, &_lock);
const Real vmax = _args.get<Real>("vmax", 1, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->clamp(vmin, vmax);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::clamp", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::clamp", e.what());
return 0;
}
}
void clampMin(const Real vmin);
static PyObject *_W_36(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::clampMin", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const Real vmin = _args.get<Real>("vmin", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->clampMin(vmin);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::clampMin", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::clampMin", e.what());
return 0;
}
}
void clampMax(const Real vmax);
static PyObject *_W_37(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::clampMax", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const Real vmax = _args.get<Real>("vmax", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->clampMax(vmax);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::clampMax", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::clampMax", e.what());
return 0;
}
}
Real getMaxAbs() const;
static PyObject *_W_38(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::getMaxAbs", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
pbo->_args.copy(_args);
_retval = toPy(pbo->getMaxAbs());
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::getMaxAbs", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::getMaxAbs", e.what());
return 0;
}
}
Real getMax() const;
static PyObject *_W_39(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::getMax", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
pbo->_args.copy(_args);
_retval = toPy(pbo->getMax());
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::getMax", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::getMax", e.what());
return 0;
}
}
Real getMin() const;
static PyObject *_W_40(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::getMin", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
pbo->_args.copy(_args);
_retval = toPy(pbo->getMin());
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::getMin", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::getMin", e.what());
return 0;
}
}
T sum(const ParticleDataImpl<int> *t = nullptr, const int itype = 0) const;
static PyObject *_W_41(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::sum", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const ParticleDataImpl<int> *t = _args.getPtrOpt<ParticleDataImpl<int>>(
"t", 0, nullptr, &_lock);
const int itype = _args.getOpt<int>("itype", 1, 0, &_lock);
pbo->_args.copy(_args);
_retval = toPy(pbo->sum(t, itype));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::sum", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::sum", e.what());
return 0;
}
}
Real sumSquare() const;
static PyObject *_W_42(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::sumSquare", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
pbo->_args.copy(_args);
_retval = toPy(pbo->sumSquare());
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::sumSquare", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::sumSquare", e.what());
return 0;
}
}
Real sumMagnitude() const;
static PyObject *_W_43(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::sumMagnitude", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
pbo->_args.copy(_args);
_retval = toPy(pbo->sumMagnitude());
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::sumMagnitude", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::sumMagnitude", e.what());
return 0;
}
}
//! special, set if int flag in t has "flag"
void setConstIntFlag(const T &s, const ParticleDataImpl<int> &t, const int flag);
static PyObject *_W_44(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::setConstIntFlag", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const T &s = *_args.getPtr<T>("s", 0, &_lock);
const ParticleDataImpl<int> &t = *_args.getPtr<ParticleDataImpl<int>>("t", 1, &_lock);
const int flag = _args.get<int>("flag", 2, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->setConstIntFlag(s, t, flag);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::setConstIntFlag", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::setConstIntFlag", e.what());
return 0;
}
}
void printPdata(IndexInt start = -1, IndexInt stop = -1, bool printIndex = false);
static PyObject *_W_45(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::printPdata", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
IndexInt start = _args.getOpt<IndexInt>("start", 0, -1, &_lock);
IndexInt stop = _args.getOpt<IndexInt>("stop", 1, -1, &_lock);
bool printIndex = _args.getOpt<bool>("printIndex", 2, false, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->printPdata(start, stop, printIndex);
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::printPdata", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::printPdata", e.what());
return 0;
}
}
//! file io
int save(const std::string name);
static PyObject *_W_46(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::save", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const std::string name = _args.get<std::string>("name", 0, &_lock);
pbo->_args.copy(_args);
_retval = toPy(pbo->save(name));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::save", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::save", e.what());
return 0;
}
}
int load(const std::string name);
static PyObject *_W_47(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::load", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const std::string name = _args.get<std::string>("name", 0, &_lock);
pbo->_args.copy(_args);
_retval = toPy(pbo->load(name));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::load", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::load", e.what());
return 0;
}
}
//! get data pointer of particle data
std::string getDataPointer();
static PyObject *_W_48(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
ParticleDataImpl *pbo = dynamic_cast<ParticleDataImpl *>(Pb::objFromPy(_self));
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(pbo->getParent(), "ParticleDataImpl::getDataPointer", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
pbo->_args.copy(_args);
_retval = toPy(pbo->getDataPointer());
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::getDataPointer", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("ParticleDataImpl::getDataPointer", e.what());
return 0;
}
}
protected:
//! data storage
std::vector<T> mData;
//! optionally , we might have an associated grid from which to grab new data
Grid<T> *mpGridSource; //! unfortunately , we need to distinguish mac vs regular vec3
bool mGridSourceMAC;
public:
PbArgs _args;
}
#define _C_ParticleDataImpl
;
//******************************************************************************
// Implementation
//******************************************************************************
const int DELETE_PART = 20; // chunk size for compression
void ParticleBase::addBuffered(const Vec3 &pos, int flag)
{
mNewBufferPos.push_back(pos);
mNewBufferFlag.push_back(flag);
}
template<class S> void ParticleSystem<S>::clear()
{
mDeleteChunk = mDeletes = 0;
this->resizeAll(0); // instead of mData.clear
}
template<class S> IndexInt ParticleSystem<S>::add(const S &data)
{
mData.push_back(data);
mDeleteChunk = mData.size() / DELETE_PART;
this->addAllPdata();
return mData.size() - 1;
}
template<class S> inline void ParticleSystem<S>::kill(IndexInt idx)
{
assertMsg(idx >= 0 && idx < size(), "Index out of bounds");
mData[idx].flag |= PDELETE;
if ((++mDeletes > mDeleteChunk) && (mAllowCompress))
compress();
}
template<class S> void ParticleSystem<S>::getPosPdata(ParticleDataImpl<Vec3> &target) const
{
for (IndexInt i = 0; i < (IndexInt)this->size(); ++i) {
target[i] = this->getPos(i);
}
}
template<class S> void ParticleSystem<S>::setPosPdata(const ParticleDataImpl<Vec3> &source)
{
for (IndexInt i = 0; i < (IndexInt)this->size(); ++i) {
this->setPos(i, source[i]);
}
}
template<class S> void ParticleSystem<S>::transformPositions(Vec3i dimOld, Vec3i dimNew)
{
const Vec3 factor = calcGridSizeFactor(dimNew, dimOld);
for (IndexInt i = 0; i < (IndexInt)this->size(); ++i) {
this->setPos(i, this->getPos(i) * factor);
}
}
// check for deletion/invalid position, otherwise return velocity
template<class S> struct _GridAdvectKernel : public KernelBase {
_GridAdvectKernel(const KernelBase &base,
std::vector<S> &p,
const MACGrid &vel,
const FlagGrid &flags,
const Real dt,
const bool deleteInObstacle,
const bool stopInObstacle,
const bool skipNew,
const ParticleDataImpl<int> *ptype,
const int exclude,
std::vector<Vec3> &u)
: KernelBase(base),
p(p),
vel(vel),
flags(flags),
dt(dt),
deleteInObstacle(deleteInObstacle),
stopInObstacle(stopInObstacle),
skipNew(skipNew),
ptype(ptype),
exclude(exclude),
u(u)
{
}
inline void op(IndexInt idx,
std::vector<S> &p,
const MACGrid &vel,
const FlagGrid &flags,
const Real dt,
const bool deleteInObstacle,
const bool stopInObstacle,
const bool skipNew,
const ParticleDataImpl<int> *ptype,
const int exclude,
std::vector<Vec3> &u) const
{
if ((p[idx].flag & ParticleBase::PDELETE) || (ptype && ((*ptype)[idx] & exclude)) ||
(skipNew && (p[idx].flag & ParticleBase::PNEW))) {
u[idx] = 0.;
return;
}
// special handling
if (deleteInObstacle || stopInObstacle) {
if (!flags.isInBounds(p[idx].pos, 1) || flags.isObstacle(p[idx].pos)) {
if (stopInObstacle)
u[idx] = 0.;
// for simple tracer particles, its convenient to delete particles right away
// for other sim types, eg flip, we can try to fix positions later on
if (deleteInObstacle)
p[idx].flag |= ParticleBase::PDELETE;
return;
}
}
u[idx] = vel.getInterpolated(p[idx].pos) * dt;
}
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, p, vel, flags, dt, deleteInObstacle, stopInObstacle, skipNew, ptype, exclude, u);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
std::vector<S> &p;
const MACGrid &vel;
const FlagGrid &flags;
const Real dt;
const bool deleteInObstacle;
const bool stopInObstacle;
const bool skipNew;
const ParticleDataImpl<int> *ptype;
const int exclude;
std::vector<Vec3> &u;
};
template<class S> struct GridAdvectKernel : public KernelBase {
GridAdvectKernel(std::vector<S> &p,
const MACGrid &vel,
const FlagGrid &flags,
const Real dt,
const bool deleteInObstacle,
const bool stopInObstacle,
const bool skipNew,
const ParticleDataImpl<int> *ptype,
const int exclude)
: KernelBase(p.size()),
_inner(KernelBase(p.size()),
p,
vel,
flags,
dt,
deleteInObstacle,
stopInObstacle,
skipNew,
ptype,
exclude,
u),
p(p),
vel(vel),
flags(flags),
dt(dt),
deleteInObstacle(deleteInObstacle),
stopInObstacle(stopInObstacle),
skipNew(skipNew),
ptype(ptype),
exclude(exclude),
u((size))
{
runMessage();
run();
}
void run()
{
_inner.run();
}
inline operator std::vector<Vec3>()
{
return u;
}
inline std::vector<Vec3> &getRet()
{
return u;
}
inline std::vector<S> &getArg0()
{
return p;
}
typedef std::vector<S> type0;
inline const MACGrid &getArg1()
{
return vel;
}
typedef MACGrid type1;
inline const FlagGrid &getArg2()
{
return flags;
}
typedef FlagGrid type2;
inline const Real &getArg3()
{
return dt;
}
typedef Real type3;
inline const bool &getArg4()
{
return deleteInObstacle;
}
typedef bool type4;
inline const bool &getArg5()
{
return stopInObstacle;
}
typedef bool type5;
inline const bool &getArg6()
{
return skipNew;
}
typedef bool type6;
inline const ParticleDataImpl<int> *getArg7()
{
return ptype;
}
typedef ParticleDataImpl<int> type7;
inline const int &getArg8()
{
return exclude;
}
typedef int type8;
void runMessage()
{
debMsg("Executing kernel GridAdvectKernel ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
_GridAdvectKernel<S> _inner;
std::vector<S> &p;
const MACGrid &vel;
const FlagGrid &flags;
const Real dt;
const bool deleteInObstacle;
const bool stopInObstacle;
const bool skipNew;
const ParticleDataImpl<int> *ptype;
const int exclude;
std::vector<Vec3> u;
};
;
// final check after advection to make sure particles haven't escaped
// (similar to particle advection kernel)
template<class S> struct KnDeleteInObstacle : public KernelBase {
KnDeleteInObstacle(std::vector<S> &p, const FlagGrid &flags)
: KernelBase(p.size()), p(p), flags(flags)
{
runMessage();
run();
}
inline void op(IndexInt idx, std::vector<S> &p, const FlagGrid &flags) const
{
if (p[idx].flag & ParticleBase::PDELETE)
return;
if (!flags.isInBounds(p[idx].pos, 1) || flags.isObstacle(p[idx].pos)) {
p[idx].flag |= ParticleBase::PDELETE;
}
}
inline std::vector<S> &getArg0()
{
return p;
}
typedef std::vector<S> type0;
inline const FlagGrid &getArg1()
{
return flags;
}
typedef FlagGrid type1;
void runMessage()
{
debMsg("Executing kernel KnDeleteInObstacle ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, p, flags);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
std::vector<S> &p;
const FlagGrid &flags;
};
// try to get closer to actual obstacle boundary
static inline Vec3 bisectBacktracePos(const FlagGrid &flags, const Vec3 &oldp, const Vec3 &newp)
{
Real s = 0.;
for (int i = 1; i < 5; ++i) {
Real ds = 1. / (Real)(1 << i);
if (!flags.isObstacle(oldp * (1. - (s + ds)) + newp * (s + ds))) {
s += ds;
}
}
return (oldp * (1. - (s)) + newp * (s));
}
// at least make sure all particles are inside domain
template<class S> struct KnClampPositions : public KernelBase {
KnClampPositions(std::vector<S> &p,
const FlagGrid &flags,
ParticleDataImpl<Vec3> *posOld = nullptr,
bool stopInObstacle = true,
const ParticleDataImpl<int> *ptype = nullptr,
const int exclude = 0)
: KernelBase(p.size()),
p(p),
flags(flags),
posOld(posOld),
stopInObstacle(stopInObstacle),
ptype(ptype),
exclude(exclude)
{
runMessage();
run();
}
inline void op(IndexInt idx,
std::vector<S> &p,
const FlagGrid &flags,
ParticleDataImpl<Vec3> *posOld = nullptr,
bool stopInObstacle = true,
const ParticleDataImpl<int> *ptype = nullptr,
const int exclude = 0) const
{
if (p[idx].flag & ParticleBase::PDELETE)
return;
if (ptype && ((*ptype)[idx] & exclude)) {
if (posOld)
p[idx].pos = (*posOld)[idx];
return;
}
if (!flags.isInBounds(p[idx].pos, 0)) {
p[idx].pos = clamp(p[idx].pos, Vec3(0.), toVec3(flags.getSize()) - Vec3(1.));
}
if (stopInObstacle && (flags.isObstacle(p[idx].pos))) {
p[idx].pos = bisectBacktracePos(flags, (*posOld)[idx], p[idx].pos);
}
}
inline std::vector<S> &getArg0()
{
return p;
}
typedef std::vector<S> type0;
inline const FlagGrid &getArg1()
{
return flags;
}
typedef FlagGrid type1;
inline ParticleDataImpl<Vec3> *getArg2()
{
return posOld;
}
typedef ParticleDataImpl<Vec3> type2;
inline bool &getArg3()
{
return stopInObstacle;
}
typedef bool type3;
inline const ParticleDataImpl<int> *getArg4()
{
return ptype;
}
typedef ParticleDataImpl<int> type4;
inline const int &getArg5()
{
return exclude;
}
typedef int type5;
void runMessage()
{
debMsg("Executing kernel KnClampPositions ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, p, flags, posOld, stopInObstacle, ptype, exclude);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
std::vector<S> &p;
const FlagGrid &flags;
ParticleDataImpl<Vec3> *posOld;
bool stopInObstacle;
const ParticleDataImpl<int> *ptype;
const int exclude;
};
// advection plugin
template<class S>
void ParticleSystem<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)
{
// position clamp requires old positions, backup
ParticleDataImpl<Vec3> *posOld = nullptr;
if (!deleteInObstacle) {
posOld = new ParticleDataImpl<Vec3>(this->getParent());
posOld->resize(mData.size());
for (IndexInt i = 0; i < (IndexInt)mData.size(); ++i)
(*posOld)[i] = mData[i].pos;
}
// update positions
GridAdvectKernel<S> kernel(mData,
vel,
flags,
getParent()->getDt(),
deleteInObstacle,
stopInObstacle,
skipNew,
ptype,
exclude);
integratePointSet(kernel, integrationMode);
if (!deleteInObstacle) {
KnClampPositions<S>(mData, flags, posOld, stopInObstacle, ptype, exclude);
delete posOld;
}
else {
KnDeleteInObstacle<S>(mData, flags);
}
}
template<class S> struct KnProjectParticles : public KernelBase {
KnProjectParticles(ParticleSystem<S> &part, Grid<Vec3> &gradient, RandomStream &rand)
: KernelBase(part.size()), part(part), gradient(gradient), rand(rand)
{
runMessage();
run();
}
inline void op(IndexInt idx, ParticleSystem<S> &part, Grid<Vec3> &gradient, RandomStream &rand)
{
const double jlen = 0.1;
if (part.isActive(idx)) {
// project along levelset gradient
Vec3 p = part[idx].pos;
if (gradient.isInBounds(p)) {
Vec3 n = gradient.getInterpolated(p);
Real dist = normalize(n);
Vec3 dx = n * (-dist + jlen * (1 + rand.getReal()));
p += dx;
}
// clamp to outer boundaries (+jitter)
const double jlen = 0.1;
Vec3 jitter = jlen * rand.getVec3();
part[idx].pos = clamp(p, Vec3(1, 1, 1) + jitter, toVec3(gradient.getSize() - 1) - jitter);
}
}
inline ParticleSystem<S> &getArg0()
{
return part;
}
typedef ParticleSystem<S> type0;
inline Grid<Vec3> &getArg1()
{
return gradient;
}
typedef Grid<Vec3> type1;
inline RandomStream &getArg2()
{
return rand;
}
typedef RandomStream type2;
void runMessage()
{
debMsg("Executing kernel KnProjectParticles ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void run()
{
const IndexInt _sz = size;
for (IndexInt i = 0; i < _sz; i++)
op(i, part, gradient, rand);
}
ParticleSystem<S> &part;
Grid<Vec3> &gradient;
RandomStream &rand;
};
template<class S> void ParticleSystem<S>::projectOutside(Grid<Vec3> &gradient)
{
RandomStream rand(globalSeed);
KnProjectParticles<S>(*this, gradient, rand);
}
template<class S> struct KnProjectOutOfBnd : public KernelBase {
KnProjectOutOfBnd(ParticleSystem<S> &part,
const FlagGrid &flags,
const Real bnd,
const bool *axis,
const ParticleDataImpl<int> *ptype,
const int exclude)
: KernelBase(part.size()),
part(part),
flags(flags),
bnd(bnd),
axis(axis),
ptype(ptype),
exclude(exclude)
{
runMessage();
run();
}
inline void op(IndexInt idx,
ParticleSystem<S> &part,
const FlagGrid &flags,
const Real bnd,
const bool *axis,
const ParticleDataImpl<int> *ptype,
const int exclude) const
{
if (!part.isActive(idx) || (ptype && ((*ptype)[idx] & exclude)))
return;
if (axis[0])
part[idx].pos.x = std::max(part[idx].pos.x, bnd);
if (axis[1])
part[idx].pos.x = std::min(part[idx].pos.x, static_cast<Real>(flags.getSizeX()) - bnd);
if (axis[2])
part[idx].pos.y = std::max(part[idx].pos.y, bnd);
if (axis[3])
part[idx].pos.y = std::min(part[idx].pos.y, static_cast<Real>(flags.getSizeY()) - bnd);
if (flags.is3D()) {
if (axis[4])
part[idx].pos.z = std::max(part[idx].pos.z, bnd);
if (axis[5])
part[idx].pos.z = std::min(part[idx].pos.z, static_cast<Real>(flags.getSizeZ()) - bnd);
}
}
inline ParticleSystem<S> &getArg0()
{
return part;
}
typedef ParticleSystem<S> type0;
inline const FlagGrid &getArg1()
{
return flags;
}
typedef FlagGrid type1;
inline const Real &getArg2()
{
return bnd;
}
typedef Real type2;
inline const bool *getArg3()
{
return axis;
}
typedef bool type3;
inline const ParticleDataImpl<int> *getArg4()
{
return ptype;
}
typedef ParticleDataImpl<int> type4;
inline const int &getArg5()
{
return exclude;
}
typedef int type5;
void runMessage()
{
debMsg("Executing kernel KnProjectOutOfBnd ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, part, flags, bnd, axis, ptype, exclude);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
ParticleSystem<S> &part;
const FlagGrid &flags;
const Real bnd;
const bool *axis;
const ParticleDataImpl<int> *ptype;
const int exclude;
};
template<class S>
void ParticleSystem<S>::projectOutOfBnd(const FlagGrid &flags,
const Real bnd,
const std::string &plane,
const ParticleDataImpl<int> *ptype,
const int exclude)
{
bool axis[6] = {false};
for (std::string::const_iterator it = plane.begin(); it != plane.end(); ++it) {
if (*it == 'x')
axis[0] = true;
if (*it == 'X')
axis[1] = true;
if (*it == 'y')
axis[2] = true;
if (*it == 'Y')
axis[3] = true;
if (*it == 'z')
axis[4] = true;
if (*it == 'Z')
axis[5] = true;
}
KnProjectOutOfBnd<S>(*this, flags, bnd, axis, ptype, exclude);
}
template<class S> void ParticleSystem<S>::resizeAll(IndexInt size)
{
// resize all buffers to target size in 1 go
mData.resize(size);
for (IndexInt i = 0; i < (IndexInt)mPartData.size(); ++i)
mPartData[i]->resize(size);
}
template<class S> void ParticleSystem<S>::compress()
{
IndexInt nextRead = mData.size();
for (IndexInt i = 0; i < (IndexInt)mData.size(); i++) {
while ((mData[i].flag & PDELETE) != 0) {
nextRead--;
mData[i] = mData[nextRead];
// ugly, but prevent virtual function calls here:
for (IndexInt pd = 0; pd < (IndexInt)mPdataReal.size(); ++pd)
mPdataReal[pd]->copyValue(nextRead, i);
for (IndexInt pd = 0; pd < (IndexInt)mPdataVec3.size(); ++pd)
mPdataVec3[pd]->copyValue(nextRead, i);
for (IndexInt pd = 0; pd < (IndexInt)mPdataInt.size(); ++pd)
mPdataInt[pd]->copyValue(nextRead, i);
mData[nextRead].flag = PINVALID;
}
}
if (nextRead < (IndexInt)mData.size())
debMsg("Deleted " << ((IndexInt)mData.size() - nextRead) << " particles", 1); // debug info
resizeAll(nextRead);
mDeletes = 0;
mDeleteChunk = mData.size() / DELETE_PART;
}
//! insert buffered positions as new particles, update additional particle data
template<class S> void ParticleSystem<S>::insertBufferedParticles()
{
// clear new flag everywhere
for (IndexInt i = 0; i < (IndexInt)mData.size(); ++i)
mData[i].flag &= ~PNEW;
if (mNewBufferPos.empty())
return;
IndexInt bufferSize = mNewBufferPos.size();
IndexInt partsSize = mData.size();
if (mMaxParticles > 0)
assertMsg(mMaxParticles >= partsSize,
"Particle system cannot contain more particles that the maximum allowed number");
// max number of new particles that can be inserted, adjusted buffer size when using maxParticles
// field
IndexInt numNewParts = (mMaxParticles > 0) ? mMaxParticles - mData.size() : bufferSize;
if (numNewParts > bufferSize)
numNewParts = bufferSize; // upper clamp
assertMsg(numNewParts >= 0, "Must not have negative number of new particles");
// new size of particle system
IndexInt newSize = mData.size() + numNewParts;
if (mMaxParticles > 0)
assertMsg(newSize <= mMaxParticles,
"Particle system cannot contain more particles that the maximum allowed number");
resizeAll(newSize);
int insertFlag;
Vec3 insertPos;
RandomStream rand(globalSeed);
for (IndexInt i = 0; i < numNewParts; ++i) {
// get random index in newBuffer vector
// we are inserting particles randomly so that they are sampled uniformly in the fluid region
// otherwise, regions of fluid can remain completely empty once mData.size() == maxParticles is
// reached.
int randIndex = floor(rand.getReal() * mNewBufferPos.size());
// get elements from new buffers with random index
std::swap(mNewBufferPos[randIndex], mNewBufferPos.back());
insertPos = mNewBufferPos.back();
mNewBufferPos.pop_back();
insertFlag = 0;
if (!mNewBufferFlag.empty()) {
std::swap(mNewBufferFlag[randIndex], mNewBufferFlag.back());
insertFlag = mNewBufferFlag.back();
mNewBufferFlag.pop_back();
}
mData[partsSize].pos = insertPos;
mData[partsSize].flag = PNEW | insertFlag;
// now init pdata fields from associated grids...
for (IndexInt pd = 0; pd < (IndexInt)mPdataReal.size(); ++pd)
mPdataReal[pd]->initNewValue(partsSize, insertPos);
for (IndexInt pd = 0; pd < (IndexInt)mPdataVec3.size(); ++pd)
mPdataVec3[pd]->initNewValue(partsSize, insertPos);
for (IndexInt pd = 0; pd < (IndexInt)mPdataInt.size(); ++pd)
mPdataInt[pd]->initNewValue(partsSize, insertPos);
partsSize++;
}
debMsg("Added & initialized " << numNewParts << " particles", 2); // debug info
mNewBufferPos.clear();
mNewBufferFlag.clear();
}
template<class DATA, class CON> void ConnectedParticleSystem<DATA, CON>::compress()
{
const IndexInt sz = ParticleSystem<DATA>::size();
IndexInt *renumber_back = new IndexInt[sz];
IndexInt *renumber = new IndexInt[sz];
for (IndexInt i = 0; i < sz; i++)
renumber[i] = renumber_back[i] = -1;
// reorder elements
std::vector<DATA> &data = ParticleSystem<DATA>::mData;
IndexInt nextRead = sz;
for (IndexInt i = 0; i < nextRead; i++) {
if ((data[i].flag & ParticleBase::PDELETE) != 0) {
nextRead--;
data[i] = data[nextRead];
data[nextRead].flag = 0;
renumber_back[i] = nextRead;
}
else
renumber_back[i] = i;
}
// acceleration structure
for (IndexInt i = 0; i < nextRead; i++)
renumber[renumber_back[i]] = i;
// rename indices in filaments
for (IndexInt i = 0; i < (IndexInt)mSegments.size(); i++)
mSegments[i].renumber(renumber);
ParticleSystem<DATA>::mData.resize(nextRead);
ParticleSystem<DATA>::mDeletes = 0;
ParticleSystem<DATA>::mDeleteChunk = ParticleSystem<DATA>::size() / DELETE_PART;
delete[] renumber;
delete[] renumber_back;
}
template<class S> ParticleBase *ParticleSystem<S>::clone()
{
ParticleSystem<S> *nm = new ParticleSystem<S>(getParent());
if (this->mAllowCompress)
compress();
nm->mData = mData;
nm->setName(getName());
this->cloneParticleData(nm);
return nm;
}
template<class DATA, class CON> ParticleBase *ConnectedParticleSystem<DATA, CON>::clone()
{
ConnectedParticleSystem<DATA, CON> *nm = new ConnectedParticleSystem<DATA, CON>(
this->getParent());
if (this->mAllowCompress)
compress();
nm->mData = this->mData;
nm->mSegments = mSegments;
nm->setName(this->getName());
this->cloneParticleData(nm);
return nm;
}
template<class S> std::string ParticleSystem<S>::infoString() const
{
std::stringstream s;
s << "ParticleSys '" << getName() << "'\n-> ";
if (this->getNumPdata() > 0)
s << "pdata: " << this->getNumPdata();
s << "parts: " << size();
// for(IndexInt i=0; i<(IndexInt)mPartData.size(); ++i) { sstr << i<<":" << mPartData[i]->size()
// <<" "; }
return s.str();
}
template<class S> inline void ParticleSystem<S>::checkPartIndex(IndexInt idx) const
{
IndexInt mySize = this->size();
if (idx < 0 || idx > mySize) {
errMsg("ParticleBase "
<< " size " << mySize << " : index " << idx << " out of bound ");
}
}
inline void ParticleDataBase::checkPartIndex(IndexInt idx) const
{
IndexInt mySize = this->getSizeSlow();
if (idx < 0 || idx > mySize) {
errMsg("ParticleData "
<< " size " << mySize << " : index " << idx << " out of bound ");
}
if (mpParticleSys && mpParticleSys->getSizeSlow() != mySize) {
errMsg("ParticleData "
<< " size " << mySize << " does not match parent! (" << mpParticleSys->getSizeSlow()
<< ") ");
}
}
// set contents to zero, as for a grid
template<class T> void ParticleDataImpl<T>::clear()
{
for (IndexInt i = 0; i < (IndexInt)mData.size(); ++i)
mData[i] = 0.;
}
//! count by type flag
int countParticles(const ParticleDataImpl<int> &t, const int flag);
} // namespace Manta
#endif