// DO NOT EDIT ! // This file is generated using the MantaFlow preprocessor (prep generate). /****************************************************************************** * * MantaFlow fluid solver framework * Copyright 2013 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 * * Particle data functionality * ******************************************************************************/ #include #include #if NO_ZLIB != 1 # include #endif #include "particle.h" #include "levelset.h" #include "mantaio.h" using namespace std; namespace Manta { ParticleBase::ParticleBase(FluidSolver *parent) : PbClass(parent), mMaxParticles(0), mAllowCompress(true), mFreePdata(false) { } ParticleBase::~ParticleBase() { // make sure data fields now parent system is deleted for (IndexInt i = 0; i < (IndexInt)mPartData.size(); ++i) mPartData[i]->setParticleSys(NULL); if (mFreePdata) { for (IndexInt i = 0; i < (IndexInt)mPartData.size(); ++i) delete mPartData[i]; } } std::string ParticleBase::infoString() const { return "ParticleSystem " + mName + " "; } void ParticleBase::cloneParticleData(ParticleBase *nm) { // clone additional data , and make sure the copied particle system deletes it nm->mFreePdata = true; for (IndexInt i = 0; i < (IndexInt)mPartData.size(); ++i) { ParticleDataBase *pdata = mPartData[i]->clone(); nm->registerPdata(pdata); } } void ParticleBase::deregister(ParticleDataBase *pdata) { bool done = false; // remove pointer from particle data list for (IndexInt i = 0; i < (IndexInt)mPartData.size(); ++i) { if (mPartData[i] == pdata) { if (i < (IndexInt)mPartData.size() - 1) mPartData[i] = mPartData[mPartData.size() - 1]; mPartData.pop_back(); done = true; } } if (!done) errMsg("Invalid pointer given, not registered!"); } // create and attach a new pdata field to this particle system PbClass *ParticleBase::create(PbType t, PbTypeVec T, const string &name) { #if NOPYTHON != 1 _args.add("nocheck", true); if (t.str() == "") errMsg("Specify particle data type to create"); // debMsg( "Pdata creating '"<< t.str <<" with size "<< this->getSizeSlow(), 5 ); PbClass *pyObj = PbClass::createPyObject(t.str() + T.str(), name, _args, this->getParent()); ParticleDataBase *pdata = dynamic_cast(pyObj); if (!pdata) { errMsg( "Unable to get particle data pointer from newly created object. Only create ParticleData " "type with a ParticleSys.creat() call, eg, PdataReal, PdataVec3 etc."); delete pyObj; return NULL; } else { this->registerPdata(pdata); } // directly init size of new pdata field: pdata->resize(this->getSizeSlow()); #else PbClass *pyObj = NULL; #endif return pyObj; } void ParticleBase::registerPdata(ParticleDataBase *pdata) { pdata->setParticleSys(this); mPartData.push_back(pdata); if (pdata->getType() == ParticleDataBase::TypeReal) { ParticleDataImpl *pd = dynamic_cast *>(pdata); if (!pd) errMsg("Invalid pdata object posing as real!"); this->registerPdataReal(pd); } else if (pdata->getType() == ParticleDataBase::TypeInt) { ParticleDataImpl *pd = dynamic_cast *>(pdata); if (!pd) errMsg("Invalid pdata object posing as int!"); this->registerPdataInt(pd); } else if (pdata->getType() == ParticleDataBase::TypeVec3) { ParticleDataImpl *pd = dynamic_cast *>(pdata); if (!pd) errMsg("Invalid pdata object posing as vec3!"); this->registerPdataVec3(pd); } } void ParticleBase::registerPdataReal(ParticleDataImpl *pd) { mPdataReal.push_back(pd); } void ParticleBase::registerPdataVec3(ParticleDataImpl *pd) { mPdataVec3.push_back(pd); } void ParticleBase::registerPdataInt(ParticleDataImpl *pd) { mPdataInt.push_back(pd); } void ParticleBase::addAllPdata() { for (IndexInt i = 0; i < (IndexInt)mPartData.size(); ++i) { mPartData[i]->addEntry(); } } BasicParticleSystem::BasicParticleSystem(FluidSolver *parent) : ParticleSystem(parent) { this->mAllowCompress = false; } // file io void BasicParticleSystem::writeParticlesText(const string name) const { ofstream ofs(name.c_str()); if (!ofs.good()) errMsg("can't open file!"); ofs << this->size() << ", pdata: " << mPartData.size() << " (" << mPdataInt.size() << "," << mPdataReal.size() << "," << mPdataVec3.size() << ") \n"; for (IndexInt i = 0; i < this->size(); ++i) { ofs << i << ": " << this->getPos(i) << " , " << this->getStatus(i) << ". "; for (IndexInt pd = 0; pd < (IndexInt)mPdataInt.size(); ++pd) ofs << mPdataInt[pd]->get(i) << " "; for (IndexInt pd = 0; pd < (IndexInt)mPdataReal.size(); ++pd) ofs << mPdataReal[pd]->get(i) << " "; for (IndexInt pd = 0; pd < (IndexInt)mPdataVec3.size(); ++pd) ofs << mPdataVec3[pd]->get(i) << " "; ofs << "\n"; } ofs.close(); } void BasicParticleSystem::writeParticlesRawPositionsGz(const string name) const { #if NO_ZLIB != 1 gzFile gzf = (gzFile)safeGzopen(name.c_str(), "wb1"); if (!gzf) errMsg("can't open file " << name); for (IndexInt i = 0; i < this->size(); ++i) { Vector3D p = toVec3f(this->getPos(i)); gzwrite(gzf, &p, sizeof(float) * 3); } gzclose(gzf); #else cout << "file format not supported without zlib" << endl; #endif } void BasicParticleSystem::writeParticlesRawVelocityGz(const string name) const { #if NO_ZLIB != 1 gzFile gzf = (gzFile)safeGzopen(name.c_str(), "wb1"); if (!gzf) errMsg("can't open file " << name); if (mPdataVec3.size() < 1) errMsg("no vec3 particle data channel found!"); // note , assuming particle data vec3 0 is velocity! make optional... for (IndexInt i = 0; i < this->size(); ++i) { Vector3D p = toVec3f(mPdataVec3[0]->get(i)); gzwrite(gzf, &p, sizeof(float) * 3); } gzclose(gzf); #else cout << "file format not supported without zlib" << endl; #endif } int BasicParticleSystem::load(const string name) { if (name.find_last_of('.') == string::npos) errMsg("file '" + name + "' does not have an extension"); string ext = name.substr(name.find_last_of('.')); if (ext == ".uni") return readParticlesUni(name, this); else if (ext == ".vdb") { std::vector parts; parts.push_back(this); return readObjectsVDB(name, &parts); } else if (ext == ".raw") // raw = uni for now return readParticlesUni(name, this); else errMsg("particle '" + name + "' filetype not supported for loading"); return 0; } int BasicParticleSystem::save(const string name) { if (name.find_last_of('.') == string::npos) errMsg("file '" + name + "' does not have an extension"); string ext = name.substr(name.find_last_of('.')); if (ext == ".txt") this->writeParticlesText(name); else if (ext == ".uni") return writeParticlesUni(name, this); else if (ext == ".raw") // raw = uni for now return writeParticlesUni(name, this); else if (ext == ".vdb") { std::vector parts; parts.push_back(this); return writeObjectsVDB(name, &parts); // raw data formats, very basic for simple data transfer to other programs } else if (ext == ".posgz") this->writeParticlesRawPositionsGz(name); else if (ext == ".velgz") this->writeParticlesRawVelocityGz(name); else errMsg("particle '" + name + "' filetype not supported for saving"); return 0; } void BasicParticleSystem::printParts(IndexInt start, IndexInt stop, bool printIndex) { std::ostringstream sstr; IndexInt s = (start > 0 ? start : 0); IndexInt e = (stop > 0 ? stop : (IndexInt)mData.size()); s = Manta::clamp(s, (IndexInt)0, (IndexInt)mData.size()); e = Manta::clamp(e, (IndexInt)0, (IndexInt)mData.size()); for (IndexInt i = s; i < e; ++i) { if (printIndex) sstr << i << ": "; sstr << mData[i].pos << " " << mData[i].flag << "\n"; } debMsg(sstr.str(), 1); } std::string BasicParticleSystem::getDataPointer() { std::ostringstream out; out << &mData; return out.str(); } void BasicParticleSystem::readParticles(BasicParticleSystem *from) { // re-allocate all data this->resizeAll(from->size()); assertMsg(from->size() == this->size(), "particle size doesn't match"); for (int i = 0; i < this->size(); ++i) { (*this)[i].pos = (*from)[i].pos; (*this)[i].flag = (*from)[i].flag; } this->transformPositions(from->getParent()->getGridSize(), this->getParent()->getGridSize()); } // particle data ParticleDataBase::ParticleDataBase(FluidSolver *parent) : PbClass(parent), mpParticleSys(NULL) { } ParticleDataBase::~ParticleDataBase() { // notify parent of deletion if (mpParticleSys) mpParticleSys->deregister(this); } // actual data implementation template ParticleDataImpl::ParticleDataImpl(FluidSolver *parent) : ParticleDataBase(parent), mpGridSource(NULL), mGridSourceMAC(false) { } template ParticleDataImpl::ParticleDataImpl(FluidSolver *parent, ParticleDataImpl *other) : ParticleDataBase(parent), mpGridSource(NULL), mGridSourceMAC(false) { this->mData = other->mData; setName(other->getName()); } template ParticleDataImpl::~ParticleDataImpl() { } template IndexInt ParticleDataImpl::getSizeSlow() const { return mData.size(); } template void ParticleDataImpl::addEntry() { // add zero'ed entry T tmp = T(0.); // for debugging, force init: // tmp = T(0.02 * mData.size()); // increasing // tmp = T(1.); // constant 1 return mData.push_back(tmp); } template void ParticleDataImpl::resize(IndexInt s) { mData.resize(s); } template void ParticleDataImpl::copyValueSlow(IndexInt from, IndexInt to) { this->copyValue(from, to); } template ParticleDataBase *ParticleDataImpl::clone() { ParticleDataImpl *npd = new ParticleDataImpl(getParent(), this); return npd; } template void ParticleDataImpl::setSource(Grid *grid, bool isMAC) { mpGridSource = grid; mGridSourceMAC = isMAC; if (grid && isMAC) assertMsg(grid->getType() & GridBase::TypeMAC, "Given grid is not a valid MAC grid"); } template void ParticleDataImpl::initNewValue(IndexInt idx, Vec3 pos) { if (!mpGridSource) mData[idx] = 0; else { mData[idx] = mpGridSource->getInterpolated(pos); } } // special handling needed for velocities template<> void ParticleDataImpl::initNewValue(IndexInt idx, Vec3 pos) { if (!mpGridSource) mData[idx] = 0; else { if (!mGridSourceMAC) mData[idx] = mpGridSource->getInterpolated(pos); else mData[idx] = ((MACGrid *)mpGridSource)->getInterpolated(pos); } } template int ParticleDataImpl::load(string name) { if (name.find_last_of('.') == string::npos) errMsg("file '" + name + "' does not have an extension"); string ext = name.substr(name.find_last_of('.')); if (ext == ".uni") return readPdataUni(name, this); else if (ext == ".vdb") { std::vector parts; parts.push_back(this); return readObjectsVDB(name, &parts); } else if (ext == ".raw") // raw = uni for now return readPdataUni(name, this); else errMsg("particle data '" + name + "' filetype not supported for loading"); return 0; } template int ParticleDataImpl::save(string name) { if (name.find_last_of('.') == string::npos) errMsg("file '" + name + "' does not have an extension"); string ext = name.substr(name.find_last_of('.')); if (ext == ".uni") return writePdataUni(name, this); else if (ext == ".vdb") { std::vector parts; parts.push_back(this); return writeObjectsVDB(name, &parts); } else if (ext == ".raw") // raw = uni for now return writePdataUni(name, this); else errMsg("particle data '" + name + "' filetype not supported for saving"); return 0; } // specializations template<> ParticleDataBase::PdataType ParticleDataImpl::getType() const { return ParticleDataBase::TypeReal; } template<> ParticleDataBase::PdataType ParticleDataImpl::getType() const { return ParticleDataBase::TypeInt; } template<> ParticleDataBase::PdataType ParticleDataImpl::getType() const { return ParticleDataBase::TypeVec3; } // note, we need a flag value for functions such as advection // ideally, this value should never be modified int ParticleIndexData::flag = 0; Vec3 ParticleIndexData::pos = Vec3(0., 0., 0.); template struct knPdataAdd : public KernelBase { knPdataAdd(ParticleDataImpl &me, const ParticleDataImpl &other) : KernelBase(me.size()), me(me), other(other) { runMessage(); run(); } inline void op(IndexInt idx, ParticleDataImpl &me, const ParticleDataImpl &other) const { me[idx] += other[idx]; } inline ParticleDataImpl &getArg0() { return me; } typedef ParticleDataImpl type0; inline const ParticleDataImpl &getArg1() { return other; } typedef ParticleDataImpl type1; void runMessage() { debMsg("Executing kernel knPdataAdd ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) const { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, me, other); } void run() { tbb::parallel_for(tbb::blocked_range(0, size), *this); } ParticleDataImpl &me; const ParticleDataImpl &other; }; template struct knPdataSub : public KernelBase { knPdataSub(ParticleDataImpl &me, const ParticleDataImpl &other) : KernelBase(me.size()), me(me), other(other) { runMessage(); run(); } inline void op(IndexInt idx, ParticleDataImpl &me, const ParticleDataImpl &other) const { me[idx] -= other[idx]; } inline ParticleDataImpl &getArg0() { return me; } typedef ParticleDataImpl type0; inline const ParticleDataImpl &getArg1() { return other; } typedef ParticleDataImpl type1; void runMessage() { debMsg("Executing kernel knPdataSub ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) const { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, me, other); } void run() { tbb::parallel_for(tbb::blocked_range(0, size), *this); } ParticleDataImpl &me; const ParticleDataImpl &other; }; template struct knPdataMult : public KernelBase { knPdataMult(ParticleDataImpl &me, const ParticleDataImpl &other) : KernelBase(me.size()), me(me), other(other) { runMessage(); run(); } inline void op(IndexInt idx, ParticleDataImpl &me, const ParticleDataImpl &other) const { me[idx] *= other[idx]; } inline ParticleDataImpl &getArg0() { return me; } typedef ParticleDataImpl type0; inline const ParticleDataImpl &getArg1() { return other; } typedef ParticleDataImpl type1; void runMessage() { debMsg("Executing kernel knPdataMult ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) const { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, me, other); } void run() { tbb::parallel_for(tbb::blocked_range(0, size), *this); } ParticleDataImpl &me; const ParticleDataImpl &other; }; template struct knPdataDiv : public KernelBase { knPdataDiv(ParticleDataImpl &me, const ParticleDataImpl &other) : KernelBase(me.size()), me(me), other(other) { runMessage(); run(); } inline void op(IndexInt idx, ParticleDataImpl &me, const ParticleDataImpl &other) const { me[idx] /= other[idx]; } inline ParticleDataImpl &getArg0() { return me; } typedef ParticleDataImpl type0; inline const ParticleDataImpl &getArg1() { return other; } typedef ParticleDataImpl type1; void runMessage() { debMsg("Executing kernel knPdataDiv ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) const { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, me, other); } void run() { tbb::parallel_for(tbb::blocked_range(0, size), *this); } ParticleDataImpl &me; const ParticleDataImpl &other; }; template struct knPdataSafeDiv : public KernelBase { knPdataSafeDiv(ParticleDataImpl &me, const ParticleDataImpl &other) : KernelBase(me.size()), me(me), other(other) { runMessage(); run(); } inline void op(IndexInt idx, ParticleDataImpl &me, const ParticleDataImpl &other) const { me[idx] = safeDivide(me[idx], other[idx]); } inline ParticleDataImpl &getArg0() { return me; } typedef ParticleDataImpl type0; inline const ParticleDataImpl &getArg1() { return other; } typedef ParticleDataImpl type1; void runMessage() { debMsg("Executing kernel knPdataSafeDiv ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) const { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, me, other); } void run() { tbb::parallel_for(tbb::blocked_range(0, size), *this); } ParticleDataImpl &me; const ParticleDataImpl &other; }; template struct knPdataSetScalar : public KernelBase { knPdataSetScalar(ParticleDataImpl &me, const S &other) : KernelBase(me.size()), me(me), other(other) { runMessage(); run(); } inline void op(IndexInt idx, ParticleDataImpl &me, const S &other) const { me[idx] = other; } inline ParticleDataImpl &getArg0() { return me; } typedef ParticleDataImpl type0; inline const S &getArg1() { return other; } typedef S type1; void runMessage() { debMsg("Executing kernel knPdataSetScalar ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) const { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, me, other); } void run() { tbb::parallel_for(tbb::blocked_range(0, size), *this); } ParticleDataImpl &me; const S &other; }; template struct knPdataAddScalar : public KernelBase { knPdataAddScalar(ParticleDataImpl &me, const S &other) : KernelBase(me.size()), me(me), other(other) { runMessage(); run(); } inline void op(IndexInt idx, ParticleDataImpl &me, const S &other) const { me[idx] += other; } inline ParticleDataImpl &getArg0() { return me; } typedef ParticleDataImpl type0; inline const S &getArg1() { return other; } typedef S type1; void runMessage() { debMsg("Executing kernel knPdataAddScalar ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) const { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, me, other); } void run() { tbb::parallel_for(tbb::blocked_range(0, size), *this); } ParticleDataImpl &me; const S &other; }; template struct knPdataMultScalar : public KernelBase { knPdataMultScalar(ParticleDataImpl &me, const S &other) : KernelBase(me.size()), me(me), other(other) { runMessage(); run(); } inline void op(IndexInt idx, ParticleDataImpl &me, const S &other) const { me[idx] *= other; } inline ParticleDataImpl &getArg0() { return me; } typedef ParticleDataImpl type0; inline const S &getArg1() { return other; } typedef S type1; void runMessage() { debMsg("Executing kernel knPdataMultScalar ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) const { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, me, other); } void run() { tbb::parallel_for(tbb::blocked_range(0, size), *this); } ParticleDataImpl &me; const S &other; }; template struct knPdataScaledAdd : public KernelBase { knPdataScaledAdd(ParticleDataImpl &me, const ParticleDataImpl &other, const S &factor) : KernelBase(me.size()), me(me), other(other), factor(factor) { runMessage(); run(); } inline void op(IndexInt idx, ParticleDataImpl &me, const ParticleDataImpl &other, const S &factor) const { me[idx] += factor * other[idx]; } inline ParticleDataImpl &getArg0() { return me; } typedef ParticleDataImpl type0; inline const ParticleDataImpl &getArg1() { return other; } typedef ParticleDataImpl type1; inline const S &getArg2() { return factor; } typedef S type2; void runMessage() { debMsg("Executing kernel knPdataScaledAdd ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) const { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, me, other, factor); } void run() { tbb::parallel_for(tbb::blocked_range(0, size), *this); } ParticleDataImpl &me; const ParticleDataImpl &other; const S &factor; }; template struct knPdataClamp : public KernelBase { knPdataClamp(ParticleDataImpl &me, const T vmin, const T vmax) : KernelBase(me.size()), me(me), vmin(vmin), vmax(vmax) { runMessage(); run(); } inline void op(IndexInt idx, ParticleDataImpl &me, const T vmin, const T vmax) const { me[idx] = clamp(me[idx], vmin, vmax); } inline ParticleDataImpl &getArg0() { return me; } typedef ParticleDataImpl type0; inline const T &getArg1() { return vmin; } typedef T type1; inline const T &getArg2() { return vmax; } typedef T type2; void runMessage() { debMsg("Executing kernel knPdataClamp ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) const { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, me, vmin, vmax); } void run() { tbb::parallel_for(tbb::blocked_range(0, size), *this); } ParticleDataImpl &me; const T vmin; const T vmax; }; template struct knPdataClampMin : public KernelBase { knPdataClampMin(ParticleDataImpl &me, const T vmin) : KernelBase(me.size()), me(me), vmin(vmin) { runMessage(); run(); } inline void op(IndexInt idx, ParticleDataImpl &me, const T vmin) const { me[idx] = std::max(vmin, me[idx]); } inline ParticleDataImpl &getArg0() { return me; } typedef ParticleDataImpl type0; inline const T &getArg1() { return vmin; } typedef T type1; void runMessage() { debMsg("Executing kernel knPdataClampMin ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) const { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, me, vmin); } void run() { tbb::parallel_for(tbb::blocked_range(0, size), *this); } ParticleDataImpl &me; const T vmin; }; template struct knPdataClampMax : public KernelBase { knPdataClampMax(ParticleDataImpl &me, const T vmax) : KernelBase(me.size()), me(me), vmax(vmax) { runMessage(); run(); } inline void op(IndexInt idx, ParticleDataImpl &me, const T vmax) const { me[idx] = std::min(vmax, me[idx]); } inline ParticleDataImpl &getArg0() { return me; } typedef ParticleDataImpl type0; inline const T &getArg1() { return vmax; } typedef T type1; void runMessage() { debMsg("Executing kernel knPdataClampMax ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) const { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, me, vmax); } void run() { tbb::parallel_for(tbb::blocked_range(0, size), *this); } ParticleDataImpl &me; const T vmax; }; struct knPdataClampMinVec3 : public KernelBase { knPdataClampMinVec3(ParticleDataImpl &me, const Real vmin) : KernelBase(me.size()), me(me), vmin(vmin) { runMessage(); run(); } inline void op(IndexInt idx, ParticleDataImpl &me, const Real vmin) const { me[idx].x = std::max(vmin, me[idx].x); me[idx].y = std::max(vmin, me[idx].y); me[idx].z = std::max(vmin, me[idx].z); } inline ParticleDataImpl &getArg0() { return me; } typedef ParticleDataImpl type0; inline const Real &getArg1() { return vmin; } typedef Real type1; void runMessage() { debMsg("Executing kernel knPdataClampMinVec3 ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) const { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, me, vmin); } void run() { tbb::parallel_for(tbb::blocked_range(0, size), *this); } ParticleDataImpl &me; const Real vmin; }; struct knPdataClampMaxVec3 : public KernelBase { knPdataClampMaxVec3(ParticleDataImpl &me, const Real vmax) : KernelBase(me.size()), me(me), vmax(vmax) { runMessage(); run(); } inline void op(IndexInt idx, ParticleDataImpl &me, const Real vmax) const { me[idx].x = std::min(vmax, me[idx].x); me[idx].y = std::min(vmax, me[idx].y); me[idx].z = std::min(vmax, me[idx].z); } inline ParticleDataImpl &getArg0() { return me; } typedef ParticleDataImpl type0; inline const Real &getArg1() { return vmax; } typedef Real type1; void runMessage() { debMsg("Executing kernel knPdataClampMaxVec3 ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) const { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, me, vmax); } void run() { tbb::parallel_for(tbb::blocked_range(0, size), *this); } ParticleDataImpl &me; const Real vmax; }; // python operators template ParticleDataImpl &ParticleDataImpl::copyFrom(const ParticleDataImpl &a) { assertMsg(a.mData.size() == mData.size(), "different pdata size " << a.mData.size() << " vs " << this->mData.size()); mData = a.mData; return *this; } template void ParticleDataImpl::setConst(const T &s) { knPdataSetScalar op(*this, s); } template void ParticleDataImpl::setConstRange(const T &s, const int begin, const int end) { for (int i = begin; i < end; ++i) (*this)[i] = s; } // special set by flag template struct knPdataSetScalarIntFlag : public KernelBase { knPdataSetScalarIntFlag(ParticleDataImpl &me, const S &other, const ParticleDataImpl &t, const int itype) : KernelBase(me.size()), me(me), other(other), t(t), itype(itype) { runMessage(); run(); } inline void op(IndexInt idx, ParticleDataImpl &me, const S &other, const ParticleDataImpl &t, const int itype) const { if (t[idx] & itype) me[idx] = other; } inline ParticleDataImpl &getArg0() { return me; } typedef ParticleDataImpl type0; inline const S &getArg1() { return other; } typedef S type1; inline const ParticleDataImpl &getArg2() { return t; } typedef ParticleDataImpl type2; inline const int &getArg3() { return itype; } typedef int type3; void runMessage() { debMsg("Executing kernel knPdataSetScalarIntFlag ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) const { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, me, other, t, itype); } void run() { tbb::parallel_for(tbb::blocked_range(0, size), *this); } ParticleDataImpl &me; const S &other; const ParticleDataImpl &t; const int itype; }; template void ParticleDataImpl::setConstIntFlag(const T &s, const ParticleDataImpl &t, const int itype) { knPdataSetScalarIntFlag op(*this, s, t, itype); } template void ParticleDataImpl::add(const ParticleDataImpl &a) { knPdataAdd op(*this, a); } template void ParticleDataImpl::sub(const ParticleDataImpl &a) { knPdataSub op(*this, a); } template void ParticleDataImpl::addConst(const T &s) { knPdataAddScalar op(*this, s); } template void ParticleDataImpl::addScaled(const ParticleDataImpl &a, const T &factor) { knPdataScaledAdd op(*this, a, factor); } template void ParticleDataImpl::mult(const ParticleDataImpl &a) { knPdataMult op(*this, a); } template void ParticleDataImpl::safeDiv(const ParticleDataImpl &a) { knPdataSafeDiv op(*this, a); } template void ParticleDataImpl::multConst(const T &s) { knPdataMultScalar op(*this, s); } template void ParticleDataImpl::clamp(const Real vmin, const Real vmax) { knPdataClamp op(*this, vmin, vmax); } template void ParticleDataImpl::clampMin(const Real vmin) { knPdataClampMin op(*this, vmin); } template void ParticleDataImpl::clampMax(const Real vmax) { knPdataClampMax op(*this, vmax); } template<> void ParticleDataImpl::clampMin(const Real vmin) { knPdataClampMinVec3 op(*this, vmin); } template<> void ParticleDataImpl::clampMax(const Real vmax) { knPdataClampMaxVec3 op(*this, vmax); } template struct KnPtsSum : public KernelBase { KnPtsSum(const ParticleDataImpl &val, const ParticleDataImpl *t, const int itype) : KernelBase(val.size()), val(val), t(t), itype(itype), result(T(0.)) { runMessage(); run(); } inline void op(IndexInt idx, const ParticleDataImpl &val, const ParticleDataImpl *t, const int itype, T &result) { if (t && !((*t)[idx] & itype)) return; result += val[idx]; } inline operator T() { return result; } inline T &getRet() { return result; } inline const ParticleDataImpl &getArg0() { return val; } typedef ParticleDataImpl type0; inline const ParticleDataImpl *getArg1() { return t; } typedef ParticleDataImpl type1; inline const int &getArg2() { return itype; } typedef int type2; void runMessage() { debMsg("Executing kernel KnPtsSum ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, val, t, itype, result); } void run() { tbb::parallel_reduce(tbb::blocked_range(0, size), *this); } KnPtsSum(KnPtsSum &o, tbb::split) : KernelBase(o), val(o.val), t(o.t), itype(o.itype), result(T(0.)) { } void join(const KnPtsSum &o) { result += o.result; } const ParticleDataImpl &val; const ParticleDataImpl *t; const int itype; T result; }; template struct KnPtsSumSquare : public KernelBase { KnPtsSumSquare(const ParticleDataImpl &val) : KernelBase(val.size()), val(val), result(0.) { runMessage(); run(); } inline void op(IndexInt idx, const ParticleDataImpl &val, Real &result) { result += normSquare(val[idx]); } inline operator Real() { return result; } inline Real &getRet() { return result; } inline const ParticleDataImpl &getArg0() { return val; } typedef ParticleDataImpl type0; void runMessage() { debMsg("Executing kernel KnPtsSumSquare ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, val, result); } void run() { tbb::parallel_reduce(tbb::blocked_range(0, size), *this); } KnPtsSumSquare(KnPtsSumSquare &o, tbb::split) : KernelBase(o), val(o.val), result(0.) { } void join(const KnPtsSumSquare &o) { result += o.result; } const ParticleDataImpl &val; Real result; }; template struct KnPtsSumMagnitude : public KernelBase { KnPtsSumMagnitude(const ParticleDataImpl &val) : KernelBase(val.size()), val(val), result(0.) { runMessage(); run(); } inline void op(IndexInt idx, const ParticleDataImpl &val, Real &result) { result += norm(val[idx]); } inline operator Real() { return result; } inline Real &getRet() { return result; } inline const ParticleDataImpl &getArg0() { return val; } typedef ParticleDataImpl type0; void runMessage() { debMsg("Executing kernel KnPtsSumMagnitude ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, val, result); } void run() { tbb::parallel_reduce(tbb::blocked_range(0, size), *this); } KnPtsSumMagnitude(KnPtsSumMagnitude &o, tbb::split) : KernelBase(o), val(o.val), result(0.) { } void join(const KnPtsSumMagnitude &o) { result += o.result; } const ParticleDataImpl &val; Real result; }; template T ParticleDataImpl::sum(const ParticleDataImpl *t, const int itype) const { return KnPtsSum(*this, t, itype); } template Real ParticleDataImpl::sumSquare() const { return KnPtsSumSquare(*this); } template Real ParticleDataImpl::sumMagnitude() const { return KnPtsSumMagnitude(*this); } template struct CompPdata_Min : public KernelBase { CompPdata_Min(const ParticleDataImpl &val) : KernelBase(val.size()), val(val), minVal(std::numeric_limits::max()) { runMessage(); run(); } inline void op(IndexInt idx, const ParticleDataImpl &val, Real &minVal) { if (val[idx] < minVal) minVal = val[idx]; } inline operator Real() { return minVal; } inline Real &getRet() { return minVal; } inline const ParticleDataImpl &getArg0() { return val; } typedef ParticleDataImpl type0; void runMessage() { debMsg("Executing kernel CompPdata_Min ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, val, minVal); } void run() { tbb::parallel_reduce(tbb::blocked_range(0, size), *this); } CompPdata_Min(CompPdata_Min &o, tbb::split) : KernelBase(o), val(o.val), minVal(std::numeric_limits::max()) { } void join(const CompPdata_Min &o) { minVal = min(minVal, o.minVal); } const ParticleDataImpl &val; Real minVal; }; template struct CompPdata_Max : public KernelBase { CompPdata_Max(const ParticleDataImpl &val) : KernelBase(val.size()), val(val), maxVal(-std::numeric_limits::max()) { runMessage(); run(); } inline void op(IndexInt idx, const ParticleDataImpl &val, Real &maxVal) { if (val[idx] > maxVal) maxVal = val[idx]; } inline operator Real() { return maxVal; } inline Real &getRet() { return maxVal; } inline const ParticleDataImpl &getArg0() { return val; } typedef ParticleDataImpl type0; void runMessage() { debMsg("Executing kernel CompPdata_Max ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, val, maxVal); } void run() { tbb::parallel_reduce(tbb::blocked_range(0, size), *this); } CompPdata_Max(CompPdata_Max &o, tbb::split) : KernelBase(o), val(o.val), maxVal(-std::numeric_limits::max()) { } void join(const CompPdata_Max &o) { maxVal = max(maxVal, o.maxVal); } const ParticleDataImpl &val; Real maxVal; }; template Real ParticleDataImpl::getMin() const { return CompPdata_Min(*this); } template Real ParticleDataImpl::getMaxAbs() const { Real amin = CompPdata_Min(*this); Real amax = CompPdata_Max(*this); return max(fabs(amin), fabs(amax)); } template Real ParticleDataImpl::getMax() const { return CompPdata_Max(*this); } template void ParticleDataImpl::printPdata(IndexInt start, IndexInt stop, bool printIndex) { std::ostringstream sstr; IndexInt s = (start > 0 ? start : 0); IndexInt e = (stop > 0 ? stop : (IndexInt)mData.size()); s = Manta::clamp(s, (IndexInt)0, (IndexInt)mData.size()); e = Manta::clamp(e, (IndexInt)0, (IndexInt)mData.size()); for (IndexInt i = s; i < e; ++i) { if (printIndex) sstr << i << ": "; sstr << mData[i] << " " << "\n"; } debMsg(sstr.str(), 1); } template std::string ParticleDataImpl::getDataPointer() { std::ostringstream out; out << &mData; return out.str(); } // specials for vec3 // work on length values, ie, always positive (in contrast to scalar versions above) struct CompPdata_MinVec3 : public KernelBase { CompPdata_MinVec3(const ParticleDataImpl &val) : KernelBase(val.size()), val(val), minVal(std::numeric_limits::max()) { runMessage(); run(); } inline void op(IndexInt idx, const ParticleDataImpl &val, Real &minVal) { const Real s = normSquare(val[idx]); if (s < minVal) minVal = s; } inline operator Real() { return minVal; } inline Real &getRet() { return minVal; } inline const ParticleDataImpl &getArg0() { return val; } typedef ParticleDataImpl type0; void runMessage() { debMsg("Executing kernel CompPdata_MinVec3 ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, val, minVal); } void run() { tbb::parallel_reduce(tbb::blocked_range(0, size), *this); } CompPdata_MinVec3(CompPdata_MinVec3 &o, tbb::split) : KernelBase(o), val(o.val), minVal(std::numeric_limits::max()) { } void join(const CompPdata_MinVec3 &o) { minVal = min(minVal, o.minVal); } const ParticleDataImpl &val; Real minVal; }; struct CompPdata_MaxVec3 : public KernelBase { CompPdata_MaxVec3(const ParticleDataImpl &val) : KernelBase(val.size()), val(val), maxVal(-std::numeric_limits::max()) { runMessage(); run(); } inline void op(IndexInt idx, const ParticleDataImpl &val, Real &maxVal) { const Real s = normSquare(val[idx]); if (s > maxVal) maxVal = s; } inline operator Real() { return maxVal; } inline Real &getRet() { return maxVal; } inline const ParticleDataImpl &getArg0() { return val; } typedef ParticleDataImpl type0; void runMessage() { debMsg("Executing kernel CompPdata_MaxVec3 ", 3); debMsg("Kernel range" << " size " << size << " ", 4); }; void operator()(const tbb::blocked_range &__r) { for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) op(idx, val, maxVal); } void run() { tbb::parallel_reduce(tbb::blocked_range(0, size), *this); } CompPdata_MaxVec3(CompPdata_MaxVec3 &o, tbb::split) : KernelBase(o), val(o.val), maxVal(-std::numeric_limits::max()) { } void join(const CompPdata_MaxVec3 &o) { maxVal = max(maxVal, o.maxVal); } const ParticleDataImpl &val; Real maxVal; }; template<> Real ParticleDataImpl::getMin() const { return sqrt(CompPdata_MinVec3(*this)); } template<> Real ParticleDataImpl::getMaxAbs() const { return sqrt(CompPdata_MaxVec3(*this)); // no minimum necessary here } template<> Real ParticleDataImpl::getMax() const { return sqrt(CompPdata_MaxVec3(*this)); } // explicit instantiation template class ParticleDataImpl; template class ParticleDataImpl; template class ParticleDataImpl; } // namespace Manta