tornavis/extern/mantaflow/preprocessed/plugin/initplugins.cpp

2583 lines
74 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
*
* Tools to setup fields and inflows
*
******************************************************************************/
#include "vectorbase.h"
#include "shapes.h"
#include "commonkernels.h"
#include "particle.h"
#include "noisefield.h"
#include "simpleimage.h"
#include "mesh.h"
using namespace std;
namespace Manta {
//! Apply noise to grid
struct KnApplyNoiseInfl : public KernelBase {
KnApplyNoiseInfl(const FlagGrid &flags,
Grid<Real> &density,
const WaveletNoiseField &noise,
const Grid<Real> &sdf,
Real scale,
Real sigma)
: KernelBase(&flags, 0),
flags(flags),
density(density),
noise(noise),
sdf(sdf),
scale(scale),
sigma(sigma)
{
runMessage();
run();
}
inline void op(int i,
int j,
int k,
const FlagGrid &flags,
Grid<Real> &density,
const WaveletNoiseField &noise,
const Grid<Real> &sdf,
Real scale,
Real sigma) const
{
if (!flags.isFluid(i, j, k) || sdf(i, j, k) > sigma)
return;
Real factor = clamp(1.0 - 0.5 / sigma * (sdf(i, j, k) + sigma), 0.0, 1.0);
Real target = noise.evaluate(Vec3(i, j, k)) * scale * factor;
if (density(i, j, k) < target)
density(i, j, k) = target;
}
inline const FlagGrid &getArg0()
{
return flags;
}
typedef FlagGrid type0;
inline Grid<Real> &getArg1()
{
return density;
}
typedef Grid<Real> type1;
inline const WaveletNoiseField &getArg2()
{
return noise;
}
typedef WaveletNoiseField type2;
inline const Grid<Real> &getArg3()
{
return sdf;
}
typedef Grid<Real> type3;
inline Real &getArg4()
{
return scale;
}
typedef Real type4;
inline Real &getArg5()
{
return sigma;
}
typedef Real type5;
void runMessage()
{
debMsg("Executing kernel KnApplyNoiseInfl ", 3);
debMsg("Kernel range"
<< " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
const int _maxX = maxX;
const int _maxY = maxY;
if (maxZ > 1) {
for (int k = __r.begin(); k != (int)__r.end(); k++)
for (int j = 0; j < _maxY; j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, flags, density, noise, sdf, scale, sigma);
}
else {
const int k = 0;
for (int j = __r.begin(); j != (int)__r.end(); j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, flags, density, noise, sdf, scale, sigma);
}
}
void run()
{
if (maxZ > 1)
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
else
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, maxY), *this);
}
const FlagGrid &flags;
Grid<Real> &density;
const WaveletNoiseField &noise;
const Grid<Real> &sdf;
Real scale;
Real sigma;
};
//! Init noise-modulated density inside shape
void densityInflow(const FlagGrid &flags,
Grid<Real> &density,
const WaveletNoiseField &noise,
Shape *shape,
Real scale = 1.0,
Real sigma = 0)
{
Grid<Real> sdf = shape->computeLevelset();
KnApplyNoiseInfl(flags, density, noise, sdf, scale, sigma);
}
static PyObject *_W_0(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "densityInflow", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
Grid<Real> &density = *_args.getPtr<Grid<Real>>("density", 1, &_lock);
const WaveletNoiseField &noise = *_args.getPtr<WaveletNoiseField>("noise", 2, &_lock);
Shape *shape = _args.getPtr<Shape>("shape", 3, &_lock);
Real scale = _args.getOpt<Real>("scale", 4, 1.0, &_lock);
Real sigma = _args.getOpt<Real>("sigma", 5, 0, &_lock);
_retval = getPyNone();
densityInflow(flags, density, noise, shape, scale, sigma);
_args.check();
}
pbFinalizePlugin(parent, "densityInflow", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("densityInflow", e.what());
return 0;
}
}
static const Pb::Register _RP_densityInflow("", "densityInflow", _W_0);
extern "C" {
void PbRegister_densityInflow()
{
KEEP_UNUSED(_RP_densityInflow);
}
}
//! Apply noise to real grid based on an SDF
struct KnAddNoise : public KernelBase {
KnAddNoise(const FlagGrid &flags,
Grid<Real> &density,
const WaveletNoiseField &noise,
const Grid<Real> *sdf,
Real scale)
: KernelBase(&flags, 0), flags(flags), density(density), noise(noise), sdf(sdf), scale(scale)
{
runMessage();
run();
}
inline void op(int i,
int j,
int k,
const FlagGrid &flags,
Grid<Real> &density,
const WaveletNoiseField &noise,
const Grid<Real> *sdf,
Real scale) const
{
if (!flags.isFluid(i, j, k) || (sdf && (*sdf)(i, j, k) > 0.))
return;
density(i, j, k) += noise.evaluate(Vec3(i, j, k)) * scale;
}
inline const FlagGrid &getArg0()
{
return flags;
}
typedef FlagGrid type0;
inline Grid<Real> &getArg1()
{
return density;
}
typedef Grid<Real> type1;
inline const WaveletNoiseField &getArg2()
{
return noise;
}
typedef WaveletNoiseField type2;
inline const Grid<Real> *getArg3()
{
return sdf;
}
typedef Grid<Real> type3;
inline Real &getArg4()
{
return scale;
}
typedef Real type4;
void runMessage()
{
debMsg("Executing kernel KnAddNoise ", 3);
debMsg("Kernel range"
<< " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
const int _maxX = maxX;
const int _maxY = maxY;
if (maxZ > 1) {
for (int k = __r.begin(); k != (int)__r.end(); k++)
for (int j = 0; j < _maxY; j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, flags, density, noise, sdf, scale);
}
else {
const int k = 0;
for (int j = __r.begin(); j != (int)__r.end(); j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, flags, density, noise, sdf, scale);
}
}
void run()
{
if (maxZ > 1)
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
else
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, maxY), *this);
}
const FlagGrid &flags;
Grid<Real> &density;
const WaveletNoiseField &noise;
const Grid<Real> *sdf;
Real scale;
};
void addNoise(const FlagGrid &flags,
Grid<Real> &density,
const WaveletNoiseField &noise,
const Grid<Real> *sdf = nullptr,
Real scale = 1.0)
{
KnAddNoise(flags, density, noise, sdf, scale);
}
static PyObject *_W_1(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "addNoise", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
Grid<Real> &density = *_args.getPtr<Grid<Real>>("density", 1, &_lock);
const WaveletNoiseField &noise = *_args.getPtr<WaveletNoiseField>("noise", 2, &_lock);
const Grid<Real> *sdf = _args.getPtrOpt<Grid<Real>>("sdf", 3, nullptr, &_lock);
Real scale = _args.getOpt<Real>("scale", 4, 1.0, &_lock);
_retval = getPyNone();
addNoise(flags, density, noise, sdf, scale);
_args.check();
}
pbFinalizePlugin(parent, "addNoise", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("addNoise", e.what());
return 0;
}
}
static const Pb::Register _RP_addNoise("", "addNoise", _W_1);
extern "C" {
void PbRegister_addNoise()
{
KEEP_UNUSED(_RP_addNoise);
}
}
//! sample noise field and set pdata with its values (for convenience, scale the noise values)
template<class T> struct knSetPdataNoise : public KernelBase {
knSetPdataNoise(const BasicParticleSystem &parts,
ParticleDataImpl<T> &pdata,
const WaveletNoiseField &noise,
Real scale)
: KernelBase(parts.size()), parts(parts), pdata(pdata), noise(noise), scale(scale)
{
runMessage();
run();
}
inline void op(IndexInt idx,
const BasicParticleSystem &parts,
ParticleDataImpl<T> &pdata,
const WaveletNoiseField &noise,
Real scale) const
{
pdata[idx] = noise.evaluate(parts.getPos(idx)) * scale;
}
inline const BasicParticleSystem &getArg0()
{
return parts;
}
typedef BasicParticleSystem type0;
inline ParticleDataImpl<T> &getArg1()
{
return pdata;
}
typedef ParticleDataImpl<T> type1;
inline const WaveletNoiseField &getArg2()
{
return noise;
}
typedef WaveletNoiseField type2;
inline Real &getArg3()
{
return scale;
}
typedef Real type3;
void runMessage()
{
debMsg("Executing kernel knSetPdataNoise ", 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, parts, pdata, noise, scale);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
const BasicParticleSystem &parts;
ParticleDataImpl<T> &pdata;
const WaveletNoiseField &noise;
Real scale;
};
template<class T> struct knSetPdataNoiseVec : public KernelBase {
knSetPdataNoiseVec(const BasicParticleSystem &parts,
ParticleDataImpl<T> &pdata,
const WaveletNoiseField &noise,
Real scale)
: KernelBase(parts.size()), parts(parts), pdata(pdata), noise(noise), scale(scale)
{
runMessage();
run();
}
inline void op(IndexInt idx,
const BasicParticleSystem &parts,
ParticleDataImpl<T> &pdata,
const WaveletNoiseField &noise,
Real scale) const
{
pdata[idx] = noise.evaluateVec(parts.getPos(idx)) * scale;
}
inline const BasicParticleSystem &getArg0()
{
return parts;
}
typedef BasicParticleSystem type0;
inline ParticleDataImpl<T> &getArg1()
{
return pdata;
}
typedef ParticleDataImpl<T> type1;
inline const WaveletNoiseField &getArg2()
{
return noise;
}
typedef WaveletNoiseField type2;
inline Real &getArg3()
{
return scale;
}
typedef Real type3;
void runMessage()
{
debMsg("Executing kernel knSetPdataNoiseVec ", 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, parts, pdata, noise, scale);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
const BasicParticleSystem &parts;
ParticleDataImpl<T> &pdata;
const WaveletNoiseField &noise;
Real scale;
};
void setNoisePdata(const BasicParticleSystem &parts,
ParticleDataImpl<Real> &pd,
const WaveletNoiseField &noise,
Real scale = 1.)
{
knSetPdataNoise<Real>(parts, pd, noise, scale);
}
static PyObject *_W_2(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "setNoisePdata", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const BasicParticleSystem &parts = *_args.getPtr<BasicParticleSystem>("parts", 0, &_lock);
ParticleDataImpl<Real> &pd = *_args.getPtr<ParticleDataImpl<Real>>("pd", 1, &_lock);
const WaveletNoiseField &noise = *_args.getPtr<WaveletNoiseField>("noise", 2, &_lock);
Real scale = _args.getOpt<Real>("scale", 3, 1., &_lock);
_retval = getPyNone();
setNoisePdata(parts, pd, noise, scale);
_args.check();
}
pbFinalizePlugin(parent, "setNoisePdata", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("setNoisePdata", e.what());
return 0;
}
}
static const Pb::Register _RP_setNoisePdata("", "setNoisePdata", _W_2);
extern "C" {
void PbRegister_setNoisePdata()
{
KEEP_UNUSED(_RP_setNoisePdata);
}
}
void setNoisePdataVec3(const BasicParticleSystem &parts,
ParticleDataImpl<Vec3> &pd,
const WaveletNoiseField &noise,
Real scale = 1.)
{
knSetPdataNoiseVec<Vec3>(parts, pd, noise, scale);
}
static PyObject *_W_3(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "setNoisePdataVec3", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const BasicParticleSystem &parts = *_args.getPtr<BasicParticleSystem>("parts", 0, &_lock);
ParticleDataImpl<Vec3> &pd = *_args.getPtr<ParticleDataImpl<Vec3>>("pd", 1, &_lock);
const WaveletNoiseField &noise = *_args.getPtr<WaveletNoiseField>("noise", 2, &_lock);
Real scale = _args.getOpt<Real>("scale", 3, 1., &_lock);
_retval = getPyNone();
setNoisePdataVec3(parts, pd, noise, scale);
_args.check();
}
pbFinalizePlugin(parent, "setNoisePdataVec3", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("setNoisePdataVec3", e.what());
return 0;
}
}
static const Pb::Register _RP_setNoisePdataVec3("", "setNoisePdataVec3", _W_3);
extern "C" {
void PbRegister_setNoisePdataVec3()
{
KEEP_UNUSED(_RP_setNoisePdataVec3);
}
}
void setNoisePdataInt(const BasicParticleSystem &parts,
ParticleDataImpl<int> &pd,
const WaveletNoiseField &noise,
Real scale = 1.)
{
knSetPdataNoise<int>(parts, pd, noise, scale);
}
static PyObject *_W_4(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "setNoisePdataInt", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const BasicParticleSystem &parts = *_args.getPtr<BasicParticleSystem>("parts", 0, &_lock);
ParticleDataImpl<int> &pd = *_args.getPtr<ParticleDataImpl<int>>("pd", 1, &_lock);
const WaveletNoiseField &noise = *_args.getPtr<WaveletNoiseField>("noise", 2, &_lock);
Real scale = _args.getOpt<Real>("scale", 3, 1., &_lock);
_retval = getPyNone();
setNoisePdataInt(parts, pd, noise, scale);
_args.check();
}
pbFinalizePlugin(parent, "setNoisePdataInt", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("setNoisePdataInt", e.what());
return 0;
}
}
static const Pb::Register _RP_setNoisePdataInt("", "setNoisePdataInt", _W_4);
extern "C" {
void PbRegister_setNoisePdataInt()
{
KEEP_UNUSED(_RP_setNoisePdataInt);
}
}
//! SDF gradient from obstacle flags, for turbulence.py
// FIXME, slow, without kernel...
Grid<Vec3> obstacleGradient(const FlagGrid &flags)
{
LevelsetGrid levelset(flags.getParent(), false);
Grid<Vec3> gradient(flags.getParent());
// rebuild obstacle levelset
FOR_IDX(levelset)
{
levelset[idx] = flags.isObstacle(idx) ? -0.5 : 0.5;
}
levelset.reinitMarching(flags, 6.0, 0, true, false, FlagGrid::TypeReserved);
// build levelset gradient
GradientOp(gradient, levelset);
FOR_IDX(levelset)
{
Vec3 grad = gradient[idx];
Real s = normalize(grad);
if (s <= 0.1 || levelset[idx] >= 0)
grad = Vec3(0.);
gradient[idx] = grad * levelset[idx];
}
return gradient;
}
static PyObject *_W_5(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "obstacleGradient", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
_retval = toPy(obstacleGradient(flags));
_args.check();
}
pbFinalizePlugin(parent, "obstacleGradient", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("obstacleGradient", e.what());
return 0;
}
}
static const Pb::Register _RP_obstacleGradient("", "obstacleGradient", _W_5);
extern "C" {
void PbRegister_obstacleGradient()
{
KEEP_UNUSED(_RP_obstacleGradient);
}
}
//! SDF from obstacle flags, for turbulence.py
LevelsetGrid obstacleLevelset(const FlagGrid &flags)
{
LevelsetGrid levelset(flags.getParent(), false);
// rebuild obstacle levelset
FOR_IDX(levelset)
{
levelset[idx] = flags.isObstacle(idx) ? -0.5 : 0.5;
}
levelset.reinitMarching(flags, 6.0, 0, true, false, FlagGrid::TypeReserved);
return levelset;
}
static PyObject *_W_6(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "obstacleLevelset", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
_retval = toPy(obstacleLevelset(flags));
_args.check();
}
pbFinalizePlugin(parent, "obstacleLevelset", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("obstacleLevelset", e.what());
return 0;
}
}
static const Pb::Register _RP_obstacleLevelset("", "obstacleLevelset", _W_6);
extern "C" {
void PbRegister_obstacleLevelset()
{
KEEP_UNUSED(_RP_obstacleLevelset);
}
}
//*****************************************************************************
// blender init functions
struct KnApplyEmission : public KernelBase {
KnApplyEmission(const FlagGrid &flags,
Grid<Real> &target,
const Grid<Real> &source,
const Grid<Real> *emissionTexture,
bool isAbsolute,
int type)
: KernelBase(&flags, 0),
flags(flags),
target(target),
source(source),
emissionTexture(emissionTexture),
isAbsolute(isAbsolute),
type(type)
{
runMessage();
run();
}
inline void op(int i,
int j,
int k,
const FlagGrid &flags,
Grid<Real> &target,
const Grid<Real> &source,
const Grid<Real> *emissionTexture,
bool isAbsolute,
int type) const
{
// if type is given, only apply emission when celltype matches type from flaggrid
// and if emission texture is given, only apply emission when some emission is present at cell
// (important for emit from particles)
bool isInflow = (type & FlagGrid::TypeInflow && flags.isInflow(i, j, k));
bool isOutflow = (type & FlagGrid::TypeOutflow && flags.isOutflow(i, j, k));
if ((type && !isInflow && !isOutflow) && (emissionTexture && !(*emissionTexture)(i, j, k)))
return;
if (isAbsolute)
target(i, j, k) = source(i, j, k);
else
target(i, j, k) += source(i, j, k);
}
inline const FlagGrid &getArg0()
{
return flags;
}
typedef FlagGrid type0;
inline Grid<Real> &getArg1()
{
return target;
}
typedef Grid<Real> type1;
inline const Grid<Real> &getArg2()
{
return source;
}
typedef Grid<Real> type2;
inline const Grid<Real> *getArg3()
{
return emissionTexture;
}
typedef Grid<Real> type3;
inline bool &getArg4()
{
return isAbsolute;
}
typedef bool type4;
inline int &getArg5()
{
return type;
}
typedef int type5;
void runMessage()
{
debMsg("Executing kernel KnApplyEmission ", 3);
debMsg("Kernel range"
<< " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
const int _maxX = maxX;
const int _maxY = maxY;
if (maxZ > 1) {
for (int k = __r.begin(); k != (int)__r.end(); k++)
for (int j = 0; j < _maxY; j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, flags, target, source, emissionTexture, isAbsolute, type);
}
else {
const int k = 0;
for (int j = __r.begin(); j != (int)__r.end(); j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, flags, target, source, emissionTexture, isAbsolute, type);
}
}
void run()
{
if (maxZ > 1)
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
else
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, maxY), *this);
}
const FlagGrid &flags;
Grid<Real> &target;
const Grid<Real> &source;
const Grid<Real> *emissionTexture;
bool isAbsolute;
int type;
};
//! Add emission values
// isAbsolute: whether to add emission values to existing, or replace
void applyEmission(FlagGrid &flags,
Grid<Real> &target,
Grid<Real> &source,
Grid<Real> *emissionTexture = nullptr,
bool isAbsolute = true,
int type = 0)
{
KnApplyEmission(flags, target, source, emissionTexture, isAbsolute, type);
}
static PyObject *_W_7(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "applyEmission", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
Grid<Real> &target = *_args.getPtr<Grid<Real>>("target", 1, &_lock);
Grid<Real> &source = *_args.getPtr<Grid<Real>>("source", 2, &_lock);
Grid<Real> *emissionTexture = _args.getPtrOpt<Grid<Real>>(
"emissionTexture", 3, nullptr, &_lock);
bool isAbsolute = _args.getOpt<bool>("isAbsolute", 4, true, &_lock);
int type = _args.getOpt<int>("type", 5, 0, &_lock);
_retval = getPyNone();
applyEmission(flags, target, source, emissionTexture, isAbsolute, type);
_args.check();
}
pbFinalizePlugin(parent, "applyEmission", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("applyEmission", e.what());
return 0;
}
}
static const Pb::Register _RP_applyEmission("", "applyEmission", _W_7);
extern "C" {
void PbRegister_applyEmission()
{
KEEP_UNUSED(_RP_applyEmission);
}
}
// blender init functions for meshes
struct KnApplyDensity : public KernelBase {
KnApplyDensity(
const FlagGrid &flags, Grid<Real> &density, const Grid<Real> &sdf, Real value, Real sigma)
: KernelBase(&flags, 0), flags(flags), density(density), sdf(sdf), value(value), sigma(sigma)
{
runMessage();
run();
}
inline void op(int i,
int j,
int k,
const FlagGrid &flags,
Grid<Real> &density,
const Grid<Real> &sdf,
Real value,
Real sigma) const
{
if (!flags.isFluid(i, j, k) || sdf(i, j, k) > sigma)
return;
density(i, j, k) = value;
}
inline const FlagGrid &getArg0()
{
return flags;
}
typedef FlagGrid type0;
inline Grid<Real> &getArg1()
{
return density;
}
typedef Grid<Real> type1;
inline const Grid<Real> &getArg2()
{
return sdf;
}
typedef Grid<Real> type2;
inline Real &getArg3()
{
return value;
}
typedef Real type3;
inline Real &getArg4()
{
return sigma;
}
typedef Real type4;
void runMessage()
{
debMsg("Executing kernel KnApplyDensity ", 3);
debMsg("Kernel range"
<< " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
const int _maxX = maxX;
const int _maxY = maxY;
if (maxZ > 1) {
for (int k = __r.begin(); k != (int)__r.end(); k++)
for (int j = 0; j < _maxY; j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, flags, density, sdf, value, sigma);
}
else {
const int k = 0;
for (int j = __r.begin(); j != (int)__r.end(); j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, flags, density, sdf, value, sigma);
}
}
void run()
{
if (maxZ > 1)
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
else
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, maxY), *this);
}
const FlagGrid &flags;
Grid<Real> &density;
const Grid<Real> &sdf;
Real value;
Real sigma;
};
//! Init noise-modulated density inside mesh
void densityInflowMeshNoise(const FlagGrid &flags,
Grid<Real> &density,
const WaveletNoiseField &noise,
Mesh *mesh,
Real scale = 1.0,
Real sigma = 0)
{
LevelsetGrid sdf(density.getParent(), false);
mesh->computeLevelset(sdf, 1.);
KnApplyNoiseInfl(flags, density, noise, sdf, scale, sigma);
}
static PyObject *_W_8(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "densityInflowMeshNoise", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
Grid<Real> &density = *_args.getPtr<Grid<Real>>("density", 1, &_lock);
const WaveletNoiseField &noise = *_args.getPtr<WaveletNoiseField>("noise", 2, &_lock);
Mesh *mesh = _args.getPtr<Mesh>("mesh", 3, &_lock);
Real scale = _args.getOpt<Real>("scale", 4, 1.0, &_lock);
Real sigma = _args.getOpt<Real>("sigma", 5, 0, &_lock);
_retval = getPyNone();
densityInflowMeshNoise(flags, density, noise, mesh, scale, sigma);
_args.check();
}
pbFinalizePlugin(parent, "densityInflowMeshNoise", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("densityInflowMeshNoise", e.what());
return 0;
}
}
static const Pb::Register _RP_densityInflowMeshNoise("", "densityInflowMeshNoise", _W_8);
extern "C" {
void PbRegister_densityInflowMeshNoise()
{
KEEP_UNUSED(_RP_densityInflowMeshNoise);
}
}
//! Init constant density inside mesh
void densityInflowMesh(const FlagGrid &flags,
Grid<Real> &density,
Mesh *mesh,
Real value = 1.,
Real cutoff = 7,
Real sigma = 0)
{
LevelsetGrid sdf(density.getParent(), false);
mesh->computeLevelset(sdf, 2., cutoff);
KnApplyDensity(flags, density, sdf, value, sigma);
}
static PyObject *_W_9(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "densityInflowMesh", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
Grid<Real> &density = *_args.getPtr<Grid<Real>>("density", 1, &_lock);
Mesh *mesh = _args.getPtr<Mesh>("mesh", 2, &_lock);
Real value = _args.getOpt<Real>("value", 3, 1., &_lock);
Real cutoff = _args.getOpt<Real>("cutoff", 4, 7, &_lock);
Real sigma = _args.getOpt<Real>("sigma", 5, 0, &_lock);
_retval = getPyNone();
densityInflowMesh(flags, density, mesh, value, cutoff, sigma);
_args.check();
}
pbFinalizePlugin(parent, "densityInflowMesh", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("densityInflowMesh", e.what());
return 0;
}
}
static const Pb::Register _RP_densityInflowMesh("", "densityInflowMesh", _W_9);
extern "C" {
void PbRegister_densityInflowMesh()
{
KEEP_UNUSED(_RP_densityInflowMesh);
}
}
struct KnResetInObstacle : public KernelBase {
KnResetInObstacle(FlagGrid &flags,
MACGrid &vel,
Grid<Real> *density,
Grid<Real> *heat,
Grid<Real> *fuel,
Grid<Real> *flame,
Grid<Real> *red,
Grid<Real> *green,
Grid<Real> *blue,
Real resetValue)
: KernelBase(&flags, 0),
flags(flags),
vel(vel),
density(density),
heat(heat),
fuel(fuel),
flame(flame),
red(red),
green(green),
blue(blue),
resetValue(resetValue)
{
runMessage();
run();
}
inline void op(int i,
int j,
int k,
FlagGrid &flags,
MACGrid &vel,
Grid<Real> *density,
Grid<Real> *heat,
Grid<Real> *fuel,
Grid<Real> *flame,
Grid<Real> *red,
Grid<Real> *green,
Grid<Real> *blue,
Real resetValue) const
{
if (!flags.isObstacle(i, j, k))
return;
vel(i, j, k).x = resetValue;
vel(i, j, k).y = resetValue;
vel(i, j, k).z = resetValue;
if (density) {
(*density)(i, j, k) = resetValue;
}
if (heat) {
(*heat)(i, j, k) = resetValue;
}
if (fuel) {
(*fuel)(i, j, k) = resetValue;
(*flame)(i, j, k) = resetValue;
}
if (red) {
(*red)(i, j, k) = resetValue;
(*green)(i, j, k) = resetValue;
(*blue)(i, j, k) = resetValue;
}
}
inline FlagGrid &getArg0()
{
return flags;
}
typedef FlagGrid type0;
inline MACGrid &getArg1()
{
return vel;
}
typedef MACGrid type1;
inline Grid<Real> *getArg2()
{
return density;
}
typedef Grid<Real> type2;
inline Grid<Real> *getArg3()
{
return heat;
}
typedef Grid<Real> type3;
inline Grid<Real> *getArg4()
{
return fuel;
}
typedef Grid<Real> type4;
inline Grid<Real> *getArg5()
{
return flame;
}
typedef Grid<Real> type5;
inline Grid<Real> *getArg6()
{
return red;
}
typedef Grid<Real> type6;
inline Grid<Real> *getArg7()
{
return green;
}
typedef Grid<Real> type7;
inline Grid<Real> *getArg8()
{
return blue;
}
typedef Grid<Real> type8;
inline Real &getArg9()
{
return resetValue;
}
typedef Real type9;
void runMessage()
{
debMsg("Executing kernel KnResetInObstacle ", 3);
debMsg("Kernel range"
<< " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
const int _maxX = maxX;
const int _maxY = maxY;
if (maxZ > 1) {
for (int k = __r.begin(); k != (int)__r.end(); k++)
for (int j = 0; j < _maxY; j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, flags, vel, density, heat, fuel, flame, red, green, blue, resetValue);
}
else {
const int k = 0;
for (int j = __r.begin(); j != (int)__r.end(); j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, flags, vel, density, heat, fuel, flame, red, green, blue, resetValue);
}
}
void run()
{
if (maxZ > 1)
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
else
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, maxY), *this);
}
FlagGrid &flags;
MACGrid &vel;
Grid<Real> *density;
Grid<Real> *heat;
Grid<Real> *fuel;
Grid<Real> *flame;
Grid<Real> *red;
Grid<Real> *green;
Grid<Real> *blue;
Real resetValue;
};
void resetInObstacle(FlagGrid &flags,
MACGrid &vel,
Grid<Real> *density,
Grid<Real> *heat = nullptr,
Grid<Real> *fuel = nullptr,
Grid<Real> *flame = nullptr,
Grid<Real> *red = nullptr,
Grid<Real> *green = nullptr,
Grid<Real> *blue = nullptr,
Real resetValue = 0)
{
KnResetInObstacle(flags, vel, density, heat, fuel, flame, red, green, blue, resetValue);
}
static PyObject *_W_10(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "resetInObstacle", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
MACGrid &vel = *_args.getPtr<MACGrid>("vel", 1, &_lock);
Grid<Real> *density = _args.getPtr<Grid<Real>>("density", 2, &_lock);
Grid<Real> *heat = _args.getPtrOpt<Grid<Real>>("heat", 3, nullptr, &_lock);
Grid<Real> *fuel = _args.getPtrOpt<Grid<Real>>("fuel", 4, nullptr, &_lock);
Grid<Real> *flame = _args.getPtrOpt<Grid<Real>>("flame", 5, nullptr, &_lock);
Grid<Real> *red = _args.getPtrOpt<Grid<Real>>("red", 6, nullptr, &_lock);
Grid<Real> *green = _args.getPtrOpt<Grid<Real>>("green", 7, nullptr, &_lock);
Grid<Real> *blue = _args.getPtrOpt<Grid<Real>>("blue", 8, nullptr, &_lock);
Real resetValue = _args.getOpt<Real>("resetValue", 9, 0, &_lock);
_retval = getPyNone();
resetInObstacle(flags, vel, density, heat, fuel, flame, red, green, blue, resetValue);
_args.check();
}
pbFinalizePlugin(parent, "resetInObstacle", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("resetInObstacle", e.what());
return 0;
}
}
static const Pb::Register _RP_resetInObstacle("", "resetInObstacle", _W_10);
extern "C" {
void PbRegister_resetInObstacle()
{
KEEP_UNUSED(_RP_resetInObstacle);
}
}
//*****************************************************************************
//! check for symmetry , optionally enfore by copying
void checkSymmetry(
Grid<Real> &a, Grid<Real> *err = nullptr, bool symmetrize = false, int axis = 0, int bound = 0)
{
const int c = axis;
const int s = a.getSize()[c];
FOR_IJK(a)
{
Vec3i idx(i, j, k), mdx(i, j, k);
mdx[c] = s - 1 - idx[c];
if (bound > 0 && ((!a.isInBounds(idx, bound)) || (!a.isInBounds(mdx, bound))))
continue;
if (err)
(*err)(idx) = fabs((double)(a(idx) - a(mdx)));
if (symmetrize && (idx[c] < s / 2)) {
a(idx) = a(mdx);
}
}
}
static PyObject *_W_11(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "checkSymmetry", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
Grid<Real> &a = *_args.getPtr<Grid<Real>>("a", 0, &_lock);
Grid<Real> *err = _args.getPtrOpt<Grid<Real>>("err", 1, nullptr, &_lock);
bool symmetrize = _args.getOpt<bool>("symmetrize", 2, false, &_lock);
int axis = _args.getOpt<int>("axis", 3, 0, &_lock);
int bound = _args.getOpt<int>("bound", 4, 0, &_lock);
_retval = getPyNone();
checkSymmetry(a, err, symmetrize, axis, bound);
_args.check();
}
pbFinalizePlugin(parent, "checkSymmetry", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("checkSymmetry", e.what());
return 0;
}
}
static const Pb::Register _RP_checkSymmetry("", "checkSymmetry", _W_11);
extern "C" {
void PbRegister_checkSymmetry()
{
KEEP_UNUSED(_RP_checkSymmetry);
}
}
//! check for symmetry , mac grid version
void checkSymmetryVec3(Grid<Vec3> &a,
Grid<Real> *err = nullptr,
bool symmetrize = false,
int axis = 0,
int bound = 0,
int disable = 0)
{
if (err)
err->setConst(0.);
// each dimension is measured separately for flexibility (could be combined)
const int c = axis;
const int o1 = (c + 1) % 3;
const int o2 = (c + 2) % 3;
// x
if (!(disable & 1)) {
const int s = a.getSize()[c] + 1;
FOR_IJK(a)
{
Vec3i idx(i, j, k), mdx(i, j, k);
mdx[c] = s - 1 - idx[c];
if (mdx[c] >= a.getSize()[c])
continue;
if (bound > 0 && ((!a.isInBounds(idx, bound)) || (!a.isInBounds(mdx, bound))))
continue;
// special case: center "line" of values , should be zero!
if (mdx[c] == idx[c]) {
if (err)
(*err)(idx) += fabs((double)(a(idx)[c]));
if (symmetrize)
a(idx)[c] = 0.;
continue;
}
// note - the a(mdx) component needs to be inverted here!
if (err)
(*err)(idx) += fabs((double)(a(idx)[c] - (a(mdx)[c] * -1.)));
if (symmetrize && (idx[c] < s / 2)) {
a(idx)[c] = a(mdx)[c] * -1.;
}
}
}
// y
if (!(disable & 2)) {
const int s = a.getSize()[c];
FOR_IJK(a)
{
Vec3i idx(i, j, k), mdx(i, j, k);
mdx[c] = s - 1 - idx[c];
if (bound > 0 && ((!a.isInBounds(idx, bound)) || (!a.isInBounds(mdx, bound))))
continue;
if (err)
(*err)(idx) += fabs((double)(a(idx)[o1] - a(mdx)[o1]));
if (symmetrize && (idx[c] < s / 2)) {
a(idx)[o1] = a(mdx)[o1];
}
}
}
// z
if (!(disable & 4)) {
const int s = a.getSize()[c];
FOR_IJK(a)
{
Vec3i idx(i, j, k), mdx(i, j, k);
mdx[c] = s - 1 - idx[c];
if (bound > 0 && ((!a.isInBounds(idx, bound)) || (!a.isInBounds(mdx, bound))))
continue;
if (err)
(*err)(idx) += fabs((double)(a(idx)[o2] - a(mdx)[o2]));
if (symmetrize && (idx[c] < s / 2)) {
a(idx)[o2] = a(mdx)[o2];
}
}
}
}
static PyObject *_W_12(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "checkSymmetryVec3", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
Grid<Vec3> &a = *_args.getPtr<Grid<Vec3>>("a", 0, &_lock);
Grid<Real> *err = _args.getPtrOpt<Grid<Real>>("err", 1, nullptr, &_lock);
bool symmetrize = _args.getOpt<bool>("symmetrize", 2, false, &_lock);
int axis = _args.getOpt<int>("axis", 3, 0, &_lock);
int bound = _args.getOpt<int>("bound", 4, 0, &_lock);
int disable = _args.getOpt<int>("disable", 5, 0, &_lock);
_retval = getPyNone();
checkSymmetryVec3(a, err, symmetrize, axis, bound, disable);
_args.check();
}
pbFinalizePlugin(parent, "checkSymmetryVec3", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("checkSymmetryVec3", e.what());
return 0;
}
}
static const Pb::Register _RP_checkSymmetryVec3("", "checkSymmetryVec3", _W_12);
extern "C" {
void PbRegister_checkSymmetryVec3()
{
KEEP_UNUSED(_RP_checkSymmetryVec3);
}
}
// from simpleimage.cpp
void projectImg(SimpleImage &img, const Grid<Real> &val, int shadeMode = 0, Real scale = 1.);
//! output shaded (all 3 axes at once for 3D)
//! shading modes: 0 smoke, 1 surfaces
void projectPpmFull(const Grid<Real> &val, string name, int shadeMode = 0, Real scale = 1.)
{
SimpleImage img;
projectImg(img, val, shadeMode, scale);
img.writePpm(name);
}
static PyObject *_W_13(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "projectPpmFull", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const Grid<Real> &val = *_args.getPtr<Grid<Real>>("val", 0, &_lock);
string name = _args.get<string>("name", 1, &_lock);
int shadeMode = _args.getOpt<int>("shadeMode", 2, 0, &_lock);
Real scale = _args.getOpt<Real>("scale", 3, 1., &_lock);
_retval = getPyNone();
projectPpmFull(val, name, shadeMode, scale);
_args.check();
}
pbFinalizePlugin(parent, "projectPpmFull", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("projectPpmFull", e.what());
return 0;
}
}
static const Pb::Register _RP_projectPpmFull("", "projectPpmFull", _W_13);
extern "C" {
void PbRegister_projectPpmFull()
{
KEEP_UNUSED(_RP_projectPpmFull);
}
}
// helper functions for pdata operator tests
//! init some test particles at the origin
void addTestParts(BasicParticleSystem &parts, int num)
{
for (int i = 0; i < num; ++i)
parts.addBuffered(Vec3(0, 0, 0));
parts.doCompress();
parts.insertBufferedParticles();
}
static PyObject *_W_14(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "addTestParts", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
BasicParticleSystem &parts = *_args.getPtr<BasicParticleSystem>("parts", 0, &_lock);
int num = _args.get<int>("num", 1, &_lock);
_retval = getPyNone();
addTestParts(parts, num);
_args.check();
}
pbFinalizePlugin(parent, "addTestParts", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("addTestParts", e.what());
return 0;
}
}
static const Pb::Register _RP_addTestParts("", "addTestParts", _W_14);
extern "C" {
void PbRegister_addTestParts()
{
KEEP_UNUSED(_RP_addTestParts);
}
}
//! calculate the difference between two pdata fields (note - slow!, not parallelized)
template<class T> Real getPdataMaxDiff(const ParticleDataImpl<T> *a, const ParticleDataImpl<T> *b)
{
assertMsg(a->getType() == b->getType(), "pdataMaxDiff problem - different pdata types!");
assertMsg(a->getSizeSlow() == b->getSizeSlow(), "pdataMaxDiff problem - different pdata sizes!");
Real maxVal = 0.;
FOR_PARTS(*a)
{
T diff = a->get(idx) - b->get(idx);
Real s = (Real)sum(abs(diff));
maxVal = std::max(maxVal, s);
}
return maxVal;
}
Real pdataMaxDiff(const ParticleDataImpl<Real> *a, const ParticleDataImpl<Real> *b)
{
return getPdataMaxDiff(a, b);
}
static PyObject *_W_15(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "pdataMaxDiff", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const ParticleDataImpl<Real> *a = _args.getPtr<ParticleDataImpl<Real>>("a", 0, &_lock);
const ParticleDataImpl<Real> *b = _args.getPtr<ParticleDataImpl<Real>>("b", 1, &_lock);
_retval = toPy(pdataMaxDiff(a, b));
_args.check();
}
pbFinalizePlugin(parent, "pdataMaxDiff", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("pdataMaxDiff", e.what());
return 0;
}
}
static const Pb::Register _RP_pdataMaxDiff("", "pdataMaxDiff", _W_15);
extern "C" {
void PbRegister_pdataMaxDiff()
{
KEEP_UNUSED(_RP_pdataMaxDiff);
}
}
Real pdataMaxDiffInt(const ParticleDataImpl<int> *a, const ParticleDataImpl<int> *b)
{
return getPdataMaxDiff(a, b);
}
static PyObject *_W_16(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "pdataMaxDiffInt", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const ParticleDataImpl<int> *a = _args.getPtr<ParticleDataImpl<int>>("a", 0, &_lock);
const ParticleDataImpl<int> *b = _args.getPtr<ParticleDataImpl<int>>("b", 1, &_lock);
_retval = toPy(pdataMaxDiffInt(a, b));
_args.check();
}
pbFinalizePlugin(parent, "pdataMaxDiffInt", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("pdataMaxDiffInt", e.what());
return 0;
}
}
static const Pb::Register _RP_pdataMaxDiffInt("", "pdataMaxDiffInt", _W_16);
extern "C" {
void PbRegister_pdataMaxDiffInt()
{
KEEP_UNUSED(_RP_pdataMaxDiffInt);
}
}
Real pdataMaxDiffVec3(const ParticleDataImpl<Vec3> *a, const ParticleDataImpl<Vec3> *b)
{
return getPdataMaxDiff(a, b);
}
static PyObject *_W_17(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "pdataMaxDiffVec3", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const ParticleDataImpl<Vec3> *a = _args.getPtr<ParticleDataImpl<Vec3>>("a", 0, &_lock);
const ParticleDataImpl<Vec3> *b = _args.getPtr<ParticleDataImpl<Vec3>>("b", 1, &_lock);
_retval = toPy(pdataMaxDiffVec3(a, b));
_args.check();
}
pbFinalizePlugin(parent, "pdataMaxDiffVec3", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("pdataMaxDiffVec3", e.what());
return 0;
}
}
static const Pb::Register _RP_pdataMaxDiffVec3("", "pdataMaxDiffVec3", _W_17);
extern "C" {
void PbRegister_pdataMaxDiffVec3()
{
KEEP_UNUSED(_RP_pdataMaxDiffVec3);
}
}
//! calculate center of mass given density grid, for re-centering
Vec3 calcCenterOfMass(const Grid<Real> &density)
{
Vec3 p(0.0f);
Real w = 0.0f;
FOR_IJK(density)
{
p += density(i, j, k) * Vec3(i + 0.5f, j + 0.5f, k + 0.5f);
w += density(i, j, k);
}
if (w > 1e-6f)
p /= w;
return p;
}
static PyObject *_W_18(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "calcCenterOfMass", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const Grid<Real> &density = *_args.getPtr<Grid<Real>>("density", 0, &_lock);
_retval = toPy(calcCenterOfMass(density));
_args.check();
}
pbFinalizePlugin(parent, "calcCenterOfMass", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("calcCenterOfMass", e.what());
return 0;
}
}
static const Pb::Register _RP_calcCenterOfMass("", "calcCenterOfMass", _W_18);
extern "C" {
void PbRegister_calcCenterOfMass()
{
KEEP_UNUSED(_RP_calcCenterOfMass);
}
}
//*****************************************************************************
// helper functions for volume fractions (which are needed for second order obstacle boundaries)
inline static Real calcFraction(Real phi1, Real phi2, Real fracThreshold)
{
if (phi1 > 0. && phi2 > 0.)
return 1.;
if (phi1 < 0. && phi2 < 0.)
return 0.;
// make sure phi1 < phi2
if (phi2 < phi1) {
Real t = phi1;
phi1 = phi2;
phi2 = t;
}
Real denom = phi1 - phi2;
if (denom > -1e-04)
return 0.5;
Real frac = 1. - phi1 / denom;
if (frac < fracThreshold)
frac = 0.; // stomp small values , dont mark as fluid
return std::min(Real(1), frac);
}
struct KnUpdateFractions : public KernelBase {
KnUpdateFractions(const FlagGrid &flags,
const Grid<Real> &phiObs,
MACGrid &fractions,
const int &boundaryWidth,
const Real fracThreshold)
: KernelBase(&flags, 1),
flags(flags),
phiObs(phiObs),
fractions(fractions),
boundaryWidth(boundaryWidth),
fracThreshold(fracThreshold)
{
runMessage();
run();
}
inline void op(int i,
int j,
int k,
const FlagGrid &flags,
const Grid<Real> &phiObs,
MACGrid &fractions,
const int &boundaryWidth,
const Real fracThreshold) const
{
// walls at domain bounds and inner objects
fractions(i, j, k).x = calcFraction(phiObs(i, j, k), phiObs(i - 1, j, k), fracThreshold);
fractions(i, j, k).y = calcFraction(phiObs(i, j, k), phiObs(i, j - 1, k), fracThreshold);
if (phiObs.is3D()) {
fractions(i, j, k).z = calcFraction(phiObs(i, j, k), phiObs(i, j, k - 1), fracThreshold);
}
// remaining BCs at the domain boundaries
const int w = boundaryWidth;
// only set if not in obstacle
if (phiObs(i, j, k) < 0.)
return;
// x-direction boundaries
if (i <= w + 1) { // min x
if ((flags.isInflow(i - 1, j, k)) || (flags.isOutflow(i - 1, j, k)) ||
(flags.isOpen(i - 1, j, k))) {
fractions(i, j, k).x = fractions(i, j, k).y = 1.;
if (flags.is3D())
fractions(i, j, k).z = 1.;
}
}
if (i >= flags.getSizeX() - w - 2) { // max x
if ((flags.isInflow(i + 1, j, k)) || (flags.isOutflow(i + 1, j, k)) ||
(flags.isOpen(i + 1, j, k))) {
fractions(i + 1, j, k).x = fractions(i + 1, j, k).y = 1.;
if (flags.is3D())
fractions(i + 1, j, k).z = 1.;
}
}
// y-direction boundaries
if (j <= w + 1) { // min y
if ((flags.isInflow(i, j - 1, k)) || (flags.isOutflow(i, j - 1, k)) ||
(flags.isOpen(i, j - 1, k))) {
fractions(i, j, k).x = fractions(i, j, k).y = 1.;
if (flags.is3D())
fractions(i, j, k).z = 1.;
}
}
if (j >= flags.getSizeY() - w - 2) { // max y
if ((flags.isInflow(i, j + 1, k)) || (flags.isOutflow(i, j + 1, k)) ||
(flags.isOpen(i, j + 1, k))) {
fractions(i, j + 1, k).x = fractions(i, j + 1, k).y = 1.;
if (flags.is3D())
fractions(i, j + 1, k).z = 1.;
}
}
// z-direction boundaries
if (flags.is3D()) {
if (k <= w + 1) { // min z
if ((flags.isInflow(i, j, k - 1)) || (flags.isOutflow(i, j, k - 1)) ||
(flags.isOpen(i, j, k - 1))) {
fractions(i, j, k).x = fractions(i, j, k).y = 1.;
if (flags.is3D())
fractions(i, j, k).z = 1.;
}
}
if (j >= flags.getSizeZ() - w - 2) { // max z
if ((flags.isInflow(i, j, k + 1)) || (flags.isOutflow(i, j, k + 1)) ||
(flags.isOpen(i, j, k + 1))) {
fractions(i, j, k + 1).x = fractions(i, j, k + 1).y = 1.;
if (flags.is3D())
fractions(i, j, k + 1).z = 1.;
}
}
}
}
inline const FlagGrid &getArg0()
{
return flags;
}
typedef FlagGrid type0;
inline const Grid<Real> &getArg1()
{
return phiObs;
}
typedef Grid<Real> type1;
inline MACGrid &getArg2()
{
return fractions;
}
typedef MACGrid type2;
inline const int &getArg3()
{
return boundaryWidth;
}
typedef int type3;
inline const Real &getArg4()
{
return fracThreshold;
}
typedef Real type4;
void runMessage()
{
debMsg("Executing kernel KnUpdateFractions ", 3);
debMsg("Kernel range"
<< " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
const int _maxX = maxX;
const int _maxY = maxY;
if (maxZ > 1) {
for (int k = __r.begin(); k != (int)__r.end(); k++)
for (int j = 1; j < _maxY; j++)
for (int i = 1; i < _maxX; i++)
op(i, j, k, flags, phiObs, fractions, boundaryWidth, fracThreshold);
}
else {
const int k = 0;
for (int j = __r.begin(); j != (int)__r.end(); j++)
for (int i = 1; i < _maxX; i++)
op(i, j, k, flags, phiObs, fractions, boundaryWidth, fracThreshold);
}
}
void run()
{
if (maxZ > 1)
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
else
tbb::parallel_for(tbb::blocked_range<IndexInt>(1, maxY), *this);
}
const FlagGrid &flags;
const Grid<Real> &phiObs;
MACGrid &fractions;
const int &boundaryWidth;
const Real fracThreshold;
};
//! update fill fraction values
void updateFractions(const FlagGrid &flags,
const Grid<Real> &phiObs,
MACGrid &fractions,
const int &boundaryWidth = 0,
const Real fracThreshold = 0.01)
{
fractions.setConst(Vec3(0.));
KnUpdateFractions(flags, phiObs, fractions, boundaryWidth, fracThreshold);
}
static PyObject *_W_19(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "updateFractions", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
const Grid<Real> &phiObs = *_args.getPtr<Grid<Real>>("phiObs", 1, &_lock);
MACGrid &fractions = *_args.getPtr<MACGrid>("fractions", 2, &_lock);
const int &boundaryWidth = _args.getOpt<int>("boundaryWidth", 3, 0, &_lock);
const Real fracThreshold = _args.getOpt<Real>("fracThreshold", 4, 0.01, &_lock);
_retval = getPyNone();
updateFractions(flags, phiObs, fractions, boundaryWidth, fracThreshold);
_args.check();
}
pbFinalizePlugin(parent, "updateFractions", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("updateFractions", e.what());
return 0;
}
}
static const Pb::Register _RP_updateFractions("", "updateFractions", _W_19);
extern "C" {
void PbRegister_updateFractions()
{
KEEP_UNUSED(_RP_updateFractions);
}
}
struct KnUpdateFlagsObs : public KernelBase {
KnUpdateFlagsObs(FlagGrid &flags,
const MACGrid *fractions,
const Grid<Real> &phiObs,
const Grid<Real> *phiOut,
const Grid<Real> *phiIn,
int boundaryWidth)
: KernelBase(&flags, boundaryWidth),
flags(flags),
fractions(fractions),
phiObs(phiObs),
phiOut(phiOut),
phiIn(phiIn),
boundaryWidth(boundaryWidth)
{
runMessage();
run();
}
inline void op(int i,
int j,
int k,
FlagGrid &flags,
const MACGrid *fractions,
const Grid<Real> &phiObs,
const Grid<Real> *phiOut,
const Grid<Real> *phiIn,
int boundaryWidth) const
{
bool isObs = false;
if (fractions) {
Real f = 0.;
f += fractions->get(i, j, k).x;
f += fractions->get(i + 1, j, k).x;
f += fractions->get(i, j, k).y;
f += fractions->get(i, j + 1, k).y;
if (flags.is3D()) {
f += fractions->get(i, j, k).z;
f += fractions->get(i, j, k + 1).z;
}
if (f == 0.)
isObs = true;
}
else {
if (phiObs(i, j, k) < 0.)
isObs = true;
}
bool isOutflow = false;
bool isInflow = false;
if (phiOut && (*phiOut)(i, j, k) < 0.)
isOutflow = true;
if (phiIn && (*phiIn)(i, j, k) < 0.)
isInflow = true;
if (isObs)
flags(i, j, k) = FlagGrid::TypeObstacle;
else if (isInflow)
flags(i, j, k) = (FlagGrid::TypeFluid | FlagGrid::TypeInflow);
else if (isOutflow)
flags(i, j, k) = (FlagGrid::TypeEmpty | FlagGrid::TypeOutflow);
else
flags(i, j, k) = FlagGrid::TypeEmpty;
}
inline FlagGrid &getArg0()
{
return flags;
}
typedef FlagGrid type0;
inline const MACGrid *getArg1()
{
return fractions;
}
typedef MACGrid type1;
inline const Grid<Real> &getArg2()
{
return phiObs;
}
typedef Grid<Real> type2;
inline const Grid<Real> *getArg3()
{
return phiOut;
}
typedef Grid<Real> type3;
inline const Grid<Real> *getArg4()
{
return phiIn;
}
typedef Grid<Real> type4;
inline int &getArg5()
{
return boundaryWidth;
}
typedef int type5;
void runMessage()
{
debMsg("Executing kernel KnUpdateFlagsObs ", 3);
debMsg("Kernel range"
<< " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
const int _maxX = maxX;
const int _maxY = maxY;
if (maxZ > 1) {
for (int k = __r.begin(); k != (int)__r.end(); k++)
for (int j = boundaryWidth; j < _maxY; j++)
for (int i = boundaryWidth; i < _maxX; i++)
op(i, j, k, flags, fractions, phiObs, phiOut, phiIn, boundaryWidth);
}
else {
const int k = 0;
for (int j = __r.begin(); j != (int)__r.end(); j++)
for (int i = boundaryWidth; i < _maxX; i++)
op(i, j, k, flags, fractions, phiObs, phiOut, phiIn, boundaryWidth);
}
}
void run()
{
if (maxZ > 1)
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
else
tbb::parallel_for(tbb::blocked_range<IndexInt>(boundaryWidth, maxY), *this);
}
FlagGrid &flags;
const MACGrid *fractions;
const Grid<Real> &phiObs;
const Grid<Real> *phiOut;
const Grid<Real> *phiIn;
int boundaryWidth;
};
//! update obstacle and outflow flags from levelsets
//! optionally uses fill fractions for obstacle
void setObstacleFlags(FlagGrid &flags,
const Grid<Real> &phiObs,
const MACGrid *fractions = nullptr,
const Grid<Real> *phiOut = nullptr,
const Grid<Real> *phiIn = nullptr,
int boundaryWidth = 1)
{
KnUpdateFlagsObs(flags, fractions, phiObs, phiOut, phiIn, boundaryWidth);
}
static PyObject *_W_20(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "setObstacleFlags", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
const Grid<Real> &phiObs = *_args.getPtr<Grid<Real>>("phiObs", 1, &_lock);
const MACGrid *fractions = _args.getPtrOpt<MACGrid>("fractions", 2, nullptr, &_lock);
const Grid<Real> *phiOut = _args.getPtrOpt<Grid<Real>>("phiOut", 3, nullptr, &_lock);
const Grid<Real> *phiIn = _args.getPtrOpt<Grid<Real>>("phiIn", 4, nullptr, &_lock);
int boundaryWidth = _args.getOpt<int>("boundaryWidth", 5, 1, &_lock);
_retval = getPyNone();
setObstacleFlags(flags, phiObs, fractions, phiOut, phiIn, boundaryWidth);
_args.check();
}
pbFinalizePlugin(parent, "setObstacleFlags", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("setObstacleFlags", e.what());
return 0;
}
}
static const Pb::Register _RP_setObstacleFlags("", "setObstacleFlags", _W_20);
extern "C" {
void PbRegister_setObstacleFlags()
{
KEEP_UNUSED(_RP_setObstacleFlags);
}
}
//! small helper for test case test_1040_secOrderBnd.py
struct kninitVortexVelocity : public KernelBase {
kninitVortexVelocity(const Grid<Real> &phiObs,
MACGrid &vel,
const Vec3 &center,
const Real &radius)
: KernelBase(&phiObs, 0), phiObs(phiObs), vel(vel), center(center), radius(radius)
{
runMessage();
run();
}
inline void op(int i,
int j,
int k,
const Grid<Real> &phiObs,
MACGrid &vel,
const Vec3 &center,
const Real &radius) const
{
if (phiObs(i, j, k) >= -1.) {
Real dx = i - center.x;
if (dx >= 0)
dx -= .5;
else
dx += .5;
Real dy = j - center.y;
Real r = std::sqrt(dx * dx + dy * dy);
Real alpha = atan2(dy, dx);
vel(i, j, k).x = -std::sin(alpha) * (r / radius);
dx = i - center.x;
dy = j - center.y;
if (dy >= 0)
dy -= .5;
else
dy += .5;
r = std::sqrt(dx * dx + dy * dy);
alpha = atan2(dy, dx);
vel(i, j, k).y = std::cos(alpha) * (r / radius);
}
}
inline const Grid<Real> &getArg0()
{
return phiObs;
}
typedef Grid<Real> type0;
inline MACGrid &getArg1()
{
return vel;
}
typedef MACGrid type1;
inline const Vec3 &getArg2()
{
return center;
}
typedef Vec3 type2;
inline const Real &getArg3()
{
return radius;
}
typedef Real type3;
void runMessage()
{
debMsg("Executing kernel kninitVortexVelocity ", 3);
debMsg("Kernel range"
<< " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
const int _maxX = maxX;
const int _maxY = maxY;
if (maxZ > 1) {
for (int k = __r.begin(); k != (int)__r.end(); k++)
for (int j = 0; j < _maxY; j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, phiObs, vel, center, radius);
}
else {
const int k = 0;
for (int j = __r.begin(); j != (int)__r.end(); j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, phiObs, vel, center, radius);
}
}
void run()
{
if (maxZ > 1)
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
else
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, maxY), *this);
}
const Grid<Real> &phiObs;
MACGrid &vel;
const Vec3 &center;
const Real &radius;
};
void initVortexVelocity(const Grid<Real> &phiObs,
MACGrid &vel,
const Vec3 &center,
const Real &radius)
{
kninitVortexVelocity(phiObs, vel, center, radius);
}
static PyObject *_W_21(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "initVortexVelocity", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
const Grid<Real> &phiObs = *_args.getPtr<Grid<Real>>("phiObs", 0, &_lock);
MACGrid &vel = *_args.getPtr<MACGrid>("vel", 1, &_lock);
const Vec3 &center = _args.get<Vec3>("center", 2, &_lock);
const Real &radius = _args.get<Real>("radius", 3, &_lock);
_retval = getPyNone();
initVortexVelocity(phiObs, vel, center, radius);
_args.check();
}
pbFinalizePlugin(parent, "initVortexVelocity", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("initVortexVelocity", e.what());
return 0;
}
}
static const Pb::Register _RP_initVortexVelocity("", "initVortexVelocity", _W_21);
extern "C" {
void PbRegister_initVortexVelocity()
{
KEEP_UNUSED(_RP_initVortexVelocity);
}
}
//*****************************************************************************
// helper functions for blurring
//! class for Gaussian Blur
struct GaussianKernelCreator {
public:
float mSigma;
int mDim;
float *mMat1D;
GaussianKernelCreator() : mSigma(0.0f), mDim(0), mMat1D(nullptr)
{
}
GaussianKernelCreator(float sigma, int dim = 0) : mSigma(0.0f), mDim(0), mMat1D(nullptr)
{
setGaussianSigma(sigma, dim);
}
Real getWeiAtDis(float disx, float disy)
{
float m = 1.0 / (sqrt(2.0 * M_PI) * mSigma);
float v = m * exp(-(1.0 * disx * disx + 1.0 * disy * disy) / (2.0 * mSigma * mSigma));
return v;
}
Real getWeiAtDis(float disx, float disy, float disz)
{
float m = 1.0 / (sqrt(2.0 * M_PI) * mSigma);
float v = m * exp(-(1.0 * disx * disx + 1.0 * disy * disy + 1.0 * disz * disz) /
(2.0 * mSigma * mSigma));
return v;
}
void setGaussianSigma(float sigma, int dim = 0)
{
mSigma = sigma;
if (dim < 3)
mDim = (int)(2.0 * 3.0 * sigma + 1.0f);
else
mDim = dim;
if (mDim < 3)
mDim = 3;
if (mDim % 2 == 0)
++mDim; // make dim odd
float s2 = mSigma * mSigma;
int c = mDim / 2;
float m = 1.0 / (sqrt(2.0 * M_PI) * mSigma);
// create 1D matrix
if (mMat1D)
delete[] mMat1D;
mMat1D = new float[mDim];
for (int i = 0; i < (mDim + 1) / 2; i++) {
float v = m * exp(-(1.0 * i * i) / (2.0 * s2));
mMat1D[c + i] = v;
mMat1D[c - i] = v;
}
}
~GaussianKernelCreator()
{
if (mMat1D)
delete[] mMat1D;
}
float get1DKernelValue(int off)
{
assertMsg(off >= 0 && off < mDim, "off exceeded boundary in Gaussian Kernel 1D!");
return mMat1D[off];
}
};
template<class T>
T convolveGrid(Grid<T> &originGrid, GaussianKernelCreator &gkSigma, Vec3 pos, int cdir)
{
// pos should be the centre pos, e.g., 1.5, 4.5, 0.5 for grid pos 1,4,0
Vec3 step(1.0, 0.0, 0.0);
if (cdir == 1) // todo, z
step = Vec3(0.0, 1.0, 0.0);
else if (cdir == 2)
step = Vec3(0.0, 0.0, 1.0);
T pxResult(0);
for (int i = 0; i < gkSigma.mDim; ++i) {
Vec3i curpos = toVec3iFloor(pos - step * (i - gkSigma.mDim / 2));
if (originGrid.isInBounds(curpos))
pxResult += gkSigma.get1DKernelValue(i) * originGrid.get(curpos);
else { // TODO , improve...
Vec3i curfitpos = curpos;
if (curfitpos.x < 0)
curfitpos.x = 0;
else if (curfitpos.x >= originGrid.getSizeX())
curfitpos.x = originGrid.getSizeX() - 1;
if (curfitpos.y < 0)
curfitpos.y = 0;
else if (curfitpos.y >= originGrid.getSizeY())
curfitpos.y = originGrid.getSizeY() - 1;
if (curfitpos.z < 0)
curfitpos.z = 0;
else if (curfitpos.z >= originGrid.getSizeZ())
curfitpos.z = originGrid.getSizeZ() - 1;
pxResult += gkSigma.get1DKernelValue(i) * originGrid.get(curfitpos);
}
}
return pxResult;
}
template<class T> struct knBlurGrid : public KernelBase {
knBlurGrid(Grid<T> &originGrid, Grid<T> &targetGrid, GaussianKernelCreator &gkSigma, int cdir)
: KernelBase(&originGrid, 0),
originGrid(originGrid),
targetGrid(targetGrid),
gkSigma(gkSigma),
cdir(cdir)
{
runMessage();
run();
}
inline void op(int i,
int j,
int k,
Grid<T> &originGrid,
Grid<T> &targetGrid,
GaussianKernelCreator &gkSigma,
int cdir) const
{
targetGrid(i, j, k) = convolveGrid<T>(originGrid, gkSigma, Vec3(i, j, k), cdir);
}
inline Grid<T> &getArg0()
{
return originGrid;
}
typedef Grid<T> type0;
inline Grid<T> &getArg1()
{
return targetGrid;
}
typedef Grid<T> type1;
inline GaussianKernelCreator &getArg2()
{
return gkSigma;
}
typedef GaussianKernelCreator type2;
inline int &getArg3()
{
return cdir;
}
typedef int type3;
void runMessage()
{
debMsg("Executing kernel knBlurGrid ", 3);
debMsg("Kernel range"
<< " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
const int _maxX = maxX;
const int _maxY = maxY;
if (maxZ > 1) {
for (int k = __r.begin(); k != (int)__r.end(); k++)
for (int j = 0; j < _maxY; j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, originGrid, targetGrid, gkSigma, cdir);
}
else {
const int k = 0;
for (int j = __r.begin(); j != (int)__r.end(); j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, originGrid, targetGrid, gkSigma, cdir);
}
}
void run()
{
if (maxZ > 1)
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
else
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, maxY), *this);
}
Grid<T> &originGrid;
Grid<T> &targetGrid;
GaussianKernelCreator &gkSigma;
int cdir;
};
template<class T> int blurGrid(Grid<T> &originGrid, Grid<T> &targetGrid, float sigma)
{
GaussianKernelCreator tmGK(sigma);
Grid<T> tmpGrid(originGrid);
knBlurGrid<T>(originGrid, tmpGrid, tmGK, 0); // blur x
knBlurGrid<T>(tmpGrid, targetGrid, tmGK, 1); // blur y
if (targetGrid.is3D()) {
tmpGrid.copyFrom(targetGrid);
knBlurGrid<T>(tmpGrid, targetGrid, tmGK, 2);
}
return tmGK.mDim;
}
struct KnBlurMACGridGauss : public KernelBase {
KnBlurMACGridGauss(MACGrid &originGrid,
MACGrid &target,
GaussianKernelCreator &gkSigma,
int cdir)
: KernelBase(&originGrid, 0),
originGrid(originGrid),
target(target),
gkSigma(gkSigma),
cdir(cdir)
{
runMessage();
run();
}
inline void op(int i,
int j,
int k,
MACGrid &originGrid,
MACGrid &target,
GaussianKernelCreator &gkSigma,
int cdir) const
{
Vec3 pos(i, j, k);
Vec3 step(1.0, 0.0, 0.0);
if (cdir == 1)
step = Vec3(0.0, 1.0, 0.0);
else if (cdir == 2)
step = Vec3(0.0, 0.0, 1.0);
Vec3 pxResult(0.0f);
for (int di = 0; di < gkSigma.mDim; ++di) {
Vec3i curpos = toVec3iFloor(pos - step * (di - gkSigma.mDim / 2));
if (!originGrid.isInBounds(curpos)) {
if (curpos.x < 0)
curpos.x = 0;
else if (curpos.x >= originGrid.getSizeX())
curpos.x = originGrid.getSizeX() - 1;
if (curpos.y < 0)
curpos.y = 0;
else if (curpos.y >= originGrid.getSizeY())
curpos.y = originGrid.getSizeY() - 1;
if (curpos.z < 0)
curpos.z = 0;
else if (curpos.z >= originGrid.getSizeZ())
curpos.z = originGrid.getSizeZ() - 1;
}
pxResult += gkSigma.get1DKernelValue(di) * originGrid.get(curpos);
}
target(i, j, k) = pxResult;
}
inline MACGrid &getArg0()
{
return originGrid;
}
typedef MACGrid type0;
inline MACGrid &getArg1()
{
return target;
}
typedef MACGrid type1;
inline GaussianKernelCreator &getArg2()
{
return gkSigma;
}
typedef GaussianKernelCreator type2;
inline int &getArg3()
{
return cdir;
}
typedef int type3;
void runMessage()
{
debMsg("Executing kernel KnBlurMACGridGauss ", 3);
debMsg("Kernel range"
<< " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
const int _maxX = maxX;
const int _maxY = maxY;
if (maxZ > 1) {
for (int k = __r.begin(); k != (int)__r.end(); k++)
for (int j = 0; j < _maxY; j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, originGrid, target, gkSigma, cdir);
}
else {
const int k = 0;
for (int j = __r.begin(); j != (int)__r.end(); j++)
for (int i = 0; i < _maxX; i++)
op(i, j, k, originGrid, target, gkSigma, cdir);
}
}
void run()
{
if (maxZ > 1)
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
else
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, maxY), *this);
}
MACGrid &originGrid;
MACGrid &target;
GaussianKernelCreator &gkSigma;
int cdir;
};
int blurMacGrid(MACGrid &oG, MACGrid &tG, float si)
{
GaussianKernelCreator tmGK(si);
MACGrid tmpGrid(oG);
KnBlurMACGridGauss(oG, tmpGrid, tmGK, 0); // blur x
KnBlurMACGridGauss(tmpGrid, tG, tmGK, 1); // blur y
if (tG.is3D()) {
tmpGrid.copyFrom(tG);
KnBlurMACGridGauss(tmpGrid, tG, tmGK, 2);
}
return tmGK.mDim;
}
static PyObject *_W_22(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "blurMacGrid", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
MACGrid &oG = *_args.getPtr<MACGrid>("oG", 0, &_lock);
MACGrid &tG = *_args.getPtr<MACGrid>("tG", 1, &_lock);
float si = _args.get<float>("si", 2, &_lock);
_retval = toPy(blurMacGrid(oG, tG, si));
_args.check();
}
pbFinalizePlugin(parent, "blurMacGrid", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("blurMacGrid", e.what());
return 0;
}
}
static const Pb::Register _RP_blurMacGrid("", "blurMacGrid", _W_22);
extern "C" {
void PbRegister_blurMacGrid()
{
KEEP_UNUSED(_RP_blurMacGrid);
}
}
int blurRealGrid(Grid<Real> &oG, Grid<Real> &tG, float si)
{
return blurGrid<Real>(oG, tG, si);
}
static PyObject *_W_23(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "blurRealGrid", !noTiming);
PyObject *_retval = nullptr;
{
ArgLocker _lock;
Grid<Real> &oG = *_args.getPtr<Grid<Real>>("oG", 0, &_lock);
Grid<Real> &tG = *_args.getPtr<Grid<Real>>("tG", 1, &_lock);
float si = _args.get<float>("si", 2, &_lock);
_retval = toPy(blurRealGrid(oG, tG, si));
_args.check();
}
pbFinalizePlugin(parent, "blurRealGrid", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("blurRealGrid", e.what());
return 0;
}
}
static const Pb::Register _RP_blurRealGrid("", "blurRealGrid", _W_23);
extern "C" {
void PbRegister_blurRealGrid()
{
KEEP_UNUSED(_RP_blurRealGrid);
}
}
} // namespace Manta