This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/extern/mantaflow/preprocessed/plugin/waveletturbulence.cpp
Sebastián Barschkis 4ff7c5eed6 Mantaflow [Part 1]: Added preprocessed Mantaflow source files
Includes preprocessed Mantaflow source files for both OpenMP and TBB (if OpenMP is not present, TBB files will be used instead).

These files come directly from the Mantaflow repository. Future updates to the core fluid solver will take place by updating the files.

Reviewed By: sergey, mont29

Maniphest Tasks: T59995

Differential Revision: https://developer.blender.org/D3850
2019-12-16 16:27:26 +01:00

1293 lines
38 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
*
* Functions for calculating wavelet turbulence,
* plus helpers to compute vorticity, and strain rate magnitude
*
******************************************************************************/
#include "vectorbase.h"
#include "shapes.h"
#include "commonkernels.h"
#include "noisefield.h"
using namespace std;
namespace Manta {
//*****************************************************************************
// first some fairly generic interpolation functions for grids with multiple sizes
//! same as in grid.h , but takes an additional optional "desired" size
inline void calcGridSizeFactorMod(
Vec3i s1, Vec3i s2, Vec3i optSize, Vec3 scale, Vec3 &sourceFactor, Vec3 &retOff)
{
for (int c = 0; c < 3; c++) {
if (optSize[c] > 0) {
s2[c] = optSize[c];
}
}
sourceFactor = calcGridSizeFactor(s1, s2) / scale;
retOff = -retOff * sourceFactor + sourceFactor * 0.5;
}
void interpolateGrid(Grid<Real> &target,
const Grid<Real> &source,
Vec3 scale = Vec3(1.),
Vec3 offset = Vec3(0.),
Vec3i size = Vec3i(-1, -1, -1),
int orderSpace = 1)
{
Vec3 sourceFactor(1.), off2 = offset;
calcGridSizeFactorMod(source.getSize(), target.getSize(), size, scale, sourceFactor, off2);
// a brief note on a mantaflow specialty: the target grid has to be the first argument here!
// the parent fluidsolver object is taken from the first grid, and it determines the size of the
// loop for the kernel call. as we're writing into target, it's important to loop exactly over
// all cells of the target grid... (note, when calling the plugin in python, it doesnt matter
// anymore).
// sourceFactor offset necessary to shift eval points by half a small cell width
knInterpolateGridTempl<Real>(target, source, sourceFactor, off2, orderSpace);
}
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, "interpolateGrid", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
Grid<Real> &target = *_args.getPtr<Grid<Real>>("target", 0, &_lock);
const Grid<Real> &source = *_args.getPtr<Grid<Real>>("source", 1, &_lock);
Vec3 scale = _args.getOpt<Vec3>("scale", 2, Vec3(1.), &_lock);
Vec3 offset = _args.getOpt<Vec3>("offset", 3, Vec3(0.), &_lock);
Vec3i size = _args.getOpt<Vec3i>("size", 4, Vec3i(-1, -1, -1), &_lock);
int orderSpace = _args.getOpt<int>("orderSpace", 5, 1, &_lock);
_retval = getPyNone();
interpolateGrid(target, source, scale, offset, size, orderSpace);
_args.check();
}
pbFinalizePlugin(parent, "interpolateGrid", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("interpolateGrid", e.what());
return 0;
}
}
static const Pb::Register _RP_interpolateGrid("", "interpolateGrid", _W_0);
extern "C" {
void PbRegister_interpolateGrid()
{
KEEP_UNUSED(_RP_interpolateGrid);
}
}
void interpolateGridVec3(Grid<Vec3> &target,
const Grid<Vec3> &source,
Vec3 scale = Vec3(1.),
Vec3 offset = Vec3(0.),
Vec3i size = Vec3i(-1, -1, -1),
int orderSpace = 1)
{
Vec3 sourceFactor(1.), off2 = offset;
calcGridSizeFactorMod(source.getSize(), target.getSize(), size, scale, sourceFactor, off2);
knInterpolateGridTempl<Vec3>(target, source, sourceFactor, off2, orderSpace);
}
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, "interpolateGridVec3", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
Grid<Vec3> &target = *_args.getPtr<Grid<Vec3>>("target", 0, &_lock);
const Grid<Vec3> &source = *_args.getPtr<Grid<Vec3>>("source", 1, &_lock);
Vec3 scale = _args.getOpt<Vec3>("scale", 2, Vec3(1.), &_lock);
Vec3 offset = _args.getOpt<Vec3>("offset", 3, Vec3(0.), &_lock);
Vec3i size = _args.getOpt<Vec3i>("size", 4, Vec3i(-1, -1, -1), &_lock);
int orderSpace = _args.getOpt<int>("orderSpace", 5, 1, &_lock);
_retval = getPyNone();
interpolateGridVec3(target, source, scale, offset, size, orderSpace);
_args.check();
}
pbFinalizePlugin(parent, "interpolateGridVec3", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("interpolateGridVec3", e.what());
return 0;
}
}
static const Pb::Register _RP_interpolateGridVec3("", "interpolateGridVec3", _W_1);
extern "C" {
void PbRegister_interpolateGridVec3()
{
KEEP_UNUSED(_RP_interpolateGridVec3);
}
}
//! interpolate a mac velocity grid from one size to another size
struct KnInterpolateMACGrid : public KernelBase {
KnInterpolateMACGrid(MACGrid &target,
const MACGrid &source,
const Vec3 &sourceFactor,
const Vec3 &off,
int orderSpace)
: KernelBase(&target, 0),
target(target),
source(source),
sourceFactor(sourceFactor),
off(off),
orderSpace(orderSpace)
{
runMessage();
run();
}
inline void op(int i,
int j,
int k,
MACGrid &target,
const MACGrid &source,
const Vec3 &sourceFactor,
const Vec3 &off,
int orderSpace) const
{
Vec3 pos = Vec3(i, j, k) * sourceFactor + off;
Real vx = source.getInterpolatedHi(pos - Vec3(0.5, 0, 0), orderSpace)[0];
Real vy = source.getInterpolatedHi(pos - Vec3(0, 0.5, 0), orderSpace)[1];
Real vz = 0.f;
if (source.is3D())
vz = source.getInterpolatedHi(pos - Vec3(0, 0, 0.5), orderSpace)[2];
target(i, j, k) = Vec3(vx, vy, vz);
}
inline MACGrid &getArg0()
{
return target;
}
typedef MACGrid type0;
inline const MACGrid &getArg1()
{
return source;
}
typedef MACGrid type1;
inline const Vec3 &getArg2()
{
return sourceFactor;
}
typedef Vec3 type2;
inline const Vec3 &getArg3()
{
return off;
}
typedef Vec3 type3;
inline int &getArg4()
{
return orderSpace;
}
typedef int type4;
void runMessage()
{
debMsg("Executing kernel KnInterpolateMACGrid ", 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, target, source, sourceFactor, off, orderSpace);
}
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, target, source, sourceFactor, off, orderSpace);
}
}
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 &target;
const MACGrid &source;
const Vec3 &sourceFactor;
const Vec3 &off;
int orderSpace;
};
void interpolateMACGrid(MACGrid &target,
const MACGrid &source,
Vec3 scale = Vec3(1.),
Vec3 offset = Vec3(0.),
Vec3i size = Vec3i(-1, -1, -1),
int orderSpace = 1)
{
Vec3 sourceFactor(1.), off2 = offset;
calcGridSizeFactorMod(source.getSize(), target.getSize(), size, scale, sourceFactor, off2);
KnInterpolateMACGrid(target, source, sourceFactor, off2, orderSpace);
}
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, "interpolateMACGrid", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
MACGrid &target = *_args.getPtr<MACGrid>("target", 0, &_lock);
const MACGrid &source = *_args.getPtr<MACGrid>("source", 1, &_lock);
Vec3 scale = _args.getOpt<Vec3>("scale", 2, Vec3(1.), &_lock);
Vec3 offset = _args.getOpt<Vec3>("offset", 3, Vec3(0.), &_lock);
Vec3i size = _args.getOpt<Vec3i>("size", 4, Vec3i(-1, -1, -1), &_lock);
int orderSpace = _args.getOpt<int>("orderSpace", 5, 1, &_lock);
_retval = getPyNone();
interpolateMACGrid(target, source, scale, offset, size, orderSpace);
_args.check();
}
pbFinalizePlugin(parent, "interpolateMACGrid", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("interpolateMACGrid", e.what());
return 0;
}
}
static const Pb::Register _RP_interpolateMACGrid("", "interpolateMACGrid", _W_2);
extern "C" {
void PbRegister_interpolateMACGrid()
{
KEEP_UNUSED(_RP_interpolateMACGrid);
}
}
//*****************************************************************************
//! Apply vector noise to grid, this is a simplified version - no position scaling or UVs
struct knApplySimpleNoiseVec3 : public KernelBase {
knApplySimpleNoiseVec3(const FlagGrid &flags,
Grid<Vec3> &target,
const WaveletNoiseField &noise,
Real scale,
const Grid<Real> *weight)
: KernelBase(&flags, 0),
flags(flags),
target(target),
noise(noise),
scale(scale),
weight(weight)
{
runMessage();
run();
}
inline void op(int i,
int j,
int k,
const FlagGrid &flags,
Grid<Vec3> &target,
const WaveletNoiseField &noise,
Real scale,
const Grid<Real> *weight) const
{
if (!flags.isFluid(i, j, k))
return;
Real factor = 1;
if (weight)
factor = (*weight)(i, j, k);
target(i, j, k) += noise.evaluateCurl(Vec3(i, j, k) + Vec3(0.5)) * scale * factor;
}
inline const FlagGrid &getArg0()
{
return flags;
}
typedef FlagGrid type0;
inline Grid<Vec3> &getArg1()
{
return target;
}
typedef Grid<Vec3> type1;
inline const WaveletNoiseField &getArg2()
{
return noise;
}
typedef WaveletNoiseField type2;
inline Real &getArg3()
{
return scale;
}
typedef Real type3;
inline const Grid<Real> *getArg4()
{
return weight;
}
typedef Grid<Real> type4;
void runMessage()
{
debMsg("Executing kernel knApplySimpleNoiseVec3 ", 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, noise, scale, weight);
}
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, noise, scale, weight);
}
}
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<Vec3> &target;
const WaveletNoiseField &noise;
Real scale;
const Grid<Real> *weight;
};
void applySimpleNoiseVec3(const FlagGrid &flags,
Grid<Vec3> &target,
const WaveletNoiseField &noise,
Real scale = 1.0,
const Grid<Real> *weight = NULL)
{
// note - passing a MAC grid here is slightly inaccurate, we should evaluate each component
// separately
knApplySimpleNoiseVec3(flags, target, noise, scale, weight);
}
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, "applySimpleNoiseVec3", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
Grid<Vec3> &target = *_args.getPtr<Grid<Vec3>>("target", 1, &_lock);
const WaveletNoiseField &noise = *_args.getPtr<WaveletNoiseField>("noise", 2, &_lock);
Real scale = _args.getOpt<Real>("scale", 3, 1.0, &_lock);
const Grid<Real> *weight = _args.getPtrOpt<Grid<Real>>("weight", 4, NULL, &_lock);
_retval = getPyNone();
applySimpleNoiseVec3(flags, target, noise, scale, weight);
_args.check();
}
pbFinalizePlugin(parent, "applySimpleNoiseVec3", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("applySimpleNoiseVec3", e.what());
return 0;
}
}
static const Pb::Register _RP_applySimpleNoiseVec3("", "applySimpleNoiseVec3", _W_3);
extern "C" {
void PbRegister_applySimpleNoiseVec3()
{
KEEP_UNUSED(_RP_applySimpleNoiseVec3);
}
}
//! Simple noise for a real grid , follows applySimpleNoiseVec3
struct knApplySimpleNoiseReal : public KernelBase {
knApplySimpleNoiseReal(const FlagGrid &flags,
Grid<Real> &target,
const WaveletNoiseField &noise,
Real scale,
const Grid<Real> *weight)
: KernelBase(&flags, 0),
flags(flags),
target(target),
noise(noise),
scale(scale),
weight(weight)
{
runMessage();
run();
}
inline void op(int i,
int j,
int k,
const FlagGrid &flags,
Grid<Real> &target,
const WaveletNoiseField &noise,
Real scale,
const Grid<Real> *weight) const
{
if (!flags.isFluid(i, j, k))
return;
Real factor = 1;
if (weight)
factor = (*weight)(i, j, k);
target(i, j, k) += noise.evaluate(Vec3(i, j, k) + Vec3(0.5)) * scale * factor;
}
inline const FlagGrid &getArg0()
{
return flags;
}
typedef FlagGrid type0;
inline Grid<Real> &getArg1()
{
return target;
}
typedef Grid<Real> type1;
inline const WaveletNoiseField &getArg2()
{
return noise;
}
typedef WaveletNoiseField type2;
inline Real &getArg3()
{
return scale;
}
typedef Real type3;
inline const Grid<Real> *getArg4()
{
return weight;
}
typedef Grid<Real> type4;
void runMessage()
{
debMsg("Executing kernel knApplySimpleNoiseReal ", 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, noise, scale, weight);
}
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, noise, scale, weight);
}
}
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 WaveletNoiseField &noise;
Real scale;
const Grid<Real> *weight;
};
void applySimpleNoiseReal(const FlagGrid &flags,
Grid<Real> &target,
const WaveletNoiseField &noise,
Real scale = 1.0,
const Grid<Real> *weight = NULL)
{
knApplySimpleNoiseReal(flags, target, noise, scale, weight);
}
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, "applySimpleNoiseReal", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
Grid<Real> &target = *_args.getPtr<Grid<Real>>("target", 1, &_lock);
const WaveletNoiseField &noise = *_args.getPtr<WaveletNoiseField>("noise", 2, &_lock);
Real scale = _args.getOpt<Real>("scale", 3, 1.0, &_lock);
const Grid<Real> *weight = _args.getPtrOpt<Grid<Real>>("weight", 4, NULL, &_lock);
_retval = getPyNone();
applySimpleNoiseReal(flags, target, noise, scale, weight);
_args.check();
}
pbFinalizePlugin(parent, "applySimpleNoiseReal", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("applySimpleNoiseReal", e.what());
return 0;
}
}
static const Pb::Register _RP_applySimpleNoiseReal("", "applySimpleNoiseReal", _W_4);
extern "C" {
void PbRegister_applySimpleNoiseReal()
{
KEEP_UNUSED(_RP_applySimpleNoiseReal);
}
}
//! Apply vector-based wavelet noise to target grid
//! This is the version with more functionality - supports uv grids, and on-the-fly interpolation
//! of input grids.
struct knApplyNoiseVec3 : public KernelBase {
knApplyNoiseVec3(const FlagGrid &flags,
Grid<Vec3> &target,
const WaveletNoiseField &noise,
Real scale,
Real scaleSpatial,
const Grid<Real> *weight,
const Grid<Vec3> *uv,
bool uvInterpol,
const Vec3 &sourceFactor)
: KernelBase(&flags, 0),
flags(flags),
target(target),
noise(noise),
scale(scale),
scaleSpatial(scaleSpatial),
weight(weight),
uv(uv),
uvInterpol(uvInterpol),
sourceFactor(sourceFactor)
{
runMessage();
run();
}
inline void op(int i,
int j,
int k,
const FlagGrid &flags,
Grid<Vec3> &target,
const WaveletNoiseField &noise,
Real scale,
Real scaleSpatial,
const Grid<Real> *weight,
const Grid<Vec3> *uv,
bool uvInterpol,
const Vec3 &sourceFactor) const
{
if (!flags.isFluid(i, j, k))
return;
// get weighting, interpolate if necessary
Real w = 1;
if (weight) {
if (!uvInterpol) {
w = (*weight)(i, j, k);
}
else {
w = weight->getInterpolated(Vec3(i, j, k) * sourceFactor);
}
}
// compute position where to evaluate the noise
Vec3 pos = Vec3(i, j, k) + Vec3(0.5);
if (uv) {
if (!uvInterpol) {
pos = (*uv)(i, j, k);
}
else {
pos = uv->getInterpolated(Vec3(i, j, k) * sourceFactor);
// uv coordinates are in local space - so we need to adjust the values of the positions
pos /= sourceFactor;
}
}
pos *= scaleSpatial;
Vec3 noiseVec3 = noise.evaluateCurl(pos) * scale * w;
// noiseVec3=pos; // debug , show interpolated positions
target(i, j, k) += noiseVec3;
}
inline const FlagGrid &getArg0()
{
return flags;
}
typedef FlagGrid type0;
inline Grid<Vec3> &getArg1()
{
return target;
}
typedef Grid<Vec3> type1;
inline const WaveletNoiseField &getArg2()
{
return noise;
}
typedef WaveletNoiseField type2;
inline Real &getArg3()
{
return scale;
}
typedef Real type3;
inline Real &getArg4()
{
return scaleSpatial;
}
typedef Real type4;
inline const Grid<Real> *getArg5()
{
return weight;
}
typedef Grid<Real> type5;
inline const Grid<Vec3> *getArg6()
{
return uv;
}
typedef Grid<Vec3> type6;
inline bool &getArg7()
{
return uvInterpol;
}
typedef bool type7;
inline const Vec3 &getArg8()
{
return sourceFactor;
}
typedef Vec3 type8;
void runMessage()
{
debMsg("Executing kernel knApplyNoiseVec3 ", 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,
noise,
scale,
scaleSpatial,
weight,
uv,
uvInterpol,
sourceFactor);
}
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,
noise,
scale,
scaleSpatial,
weight,
uv,
uvInterpol,
sourceFactor);
}
}
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<Vec3> &target;
const WaveletNoiseField &noise;
Real scale;
Real scaleSpatial;
const Grid<Real> *weight;
const Grid<Vec3> *uv;
bool uvInterpol;
const Vec3 &sourceFactor;
};
void applyNoiseVec3(const FlagGrid &flags,
Grid<Vec3> &target,
const WaveletNoiseField &noise,
Real scale = 1.0,
Real scaleSpatial = 1.0,
const Grid<Real> *weight = NULL,
const Grid<Vec3> *uv = NULL)
{
// check whether the uv grid has a different resolution
bool uvInterpol = false;
// and pre-compute conversion (only used if uvInterpol==true)
// used for both uv and weight grid...
Vec3 sourceFactor = Vec3(1.);
if (uv) {
uvInterpol = (target.getSize() != uv->getSize());
sourceFactor = calcGridSizeFactor(uv->getSize(), target.getSize());
}
else if (weight) {
uvInterpol = (target.getSize() != weight->getSize());
sourceFactor = calcGridSizeFactor(weight->getSize(), target.getSize());
}
if (uv && weight)
assertMsg(uv->getSize() == weight->getSize(), "UV and weight grid have to match!");
// note - passing a MAC grid here is slightly inaccurate, we should evaluate each component
// separately
knApplyNoiseVec3(
flags, target, noise, scale, scaleSpatial, weight, uv, uvInterpol, sourceFactor);
}
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, "applyNoiseVec3", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
Grid<Vec3> &target = *_args.getPtr<Grid<Vec3>>("target", 1, &_lock);
const WaveletNoiseField &noise = *_args.getPtr<WaveletNoiseField>("noise", 2, &_lock);
Real scale = _args.getOpt<Real>("scale", 3, 1.0, &_lock);
Real scaleSpatial = _args.getOpt<Real>("scaleSpatial", 4, 1.0, &_lock);
const Grid<Real> *weight = _args.getPtrOpt<Grid<Real>>("weight", 5, NULL, &_lock);
const Grid<Vec3> *uv = _args.getPtrOpt<Grid<Vec3>>("uv", 6, NULL, &_lock);
_retval = getPyNone();
applyNoiseVec3(flags, target, noise, scale, scaleSpatial, weight, uv);
_args.check();
}
pbFinalizePlugin(parent, "applyNoiseVec3", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("applyNoiseVec3", e.what());
return 0;
}
}
static const Pb::Register _RP_applyNoiseVec3("", "applyNoiseVec3", _W_5);
extern "C" {
void PbRegister_applyNoiseVec3()
{
KEEP_UNUSED(_RP_applyNoiseVec3);
}
}
//! Compute energy of a staggered velocity field (at cell center)
struct KnApplyComputeEnergy : public KernelBase {
KnApplyComputeEnergy(const FlagGrid &flags, const MACGrid &vel, Grid<Real> &energy)
: KernelBase(&flags, 0), flags(flags), vel(vel), energy(energy)
{
runMessage();
run();
}
inline void op(
int i, int j, int k, const FlagGrid &flags, const MACGrid &vel, Grid<Real> &energy) const
{
Real e = 0.f;
if (flags.isFluid(i, j, k)) {
Vec3 v = vel.getCentered(i, j, k);
e = 0.5 * (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
}
energy(i, j, k) = e;
}
inline const FlagGrid &getArg0()
{
return flags;
}
typedef FlagGrid type0;
inline const MACGrid &getArg1()
{
return vel;
}
typedef MACGrid type1;
inline Grid<Real> &getArg2()
{
return energy;
}
typedef Grid<Real> type2;
void runMessage()
{
debMsg("Executing kernel KnApplyComputeEnergy ", 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, energy);
}
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, energy);
}
}
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;
const MACGrid &vel;
Grid<Real> &energy;
};
void computeEnergy(const FlagGrid &flags, const MACGrid &vel, Grid<Real> &energy)
{
KnApplyComputeEnergy(flags, vel, energy);
}
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, "computeEnergy", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
const MACGrid &vel = *_args.getPtr<MACGrid>("vel", 1, &_lock);
Grid<Real> &energy = *_args.getPtr<Grid<Real>>("energy", 2, &_lock);
_retval = getPyNone();
computeEnergy(flags, vel, energy);
_args.check();
}
pbFinalizePlugin(parent, "computeEnergy", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("computeEnergy", e.what());
return 0;
}
}
static const Pb::Register _RP_computeEnergy("", "computeEnergy", _W_6);
extern "C" {
void PbRegister_computeEnergy()
{
KEEP_UNUSED(_RP_computeEnergy);
}
}
void computeWaveletCoeffs(Grid<Real> &input)
{
Grid<Real> temp1(input.getParent()), temp2(input.getParent());
WaveletNoiseField::computeCoefficients(input, temp1, temp2);
}
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, "computeWaveletCoeffs", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
Grid<Real> &input = *_args.getPtr<Grid<Real>>("input", 0, &_lock);
_retval = getPyNone();
computeWaveletCoeffs(input);
_args.check();
}
pbFinalizePlugin(parent, "computeWaveletCoeffs", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("computeWaveletCoeffs", e.what());
return 0;
}
}
static const Pb::Register _RP_computeWaveletCoeffs("", "computeWaveletCoeffs", _W_7);
extern "C" {
void PbRegister_computeWaveletCoeffs()
{
KEEP_UNUSED(_RP_computeWaveletCoeffs);
}
}
// note - alomst the same as for vorticity confinement
void computeVorticity(const MACGrid &vel, Grid<Vec3> &vorticity, Grid<Real> *norm = NULL)
{
Grid<Vec3> velCenter(vel.getParent());
GetCentered(velCenter, vel);
CurlOp(velCenter, vorticity);
if (norm)
GridNorm(*norm, vorticity);
}
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, "computeVorticity", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
const MACGrid &vel = *_args.getPtr<MACGrid>("vel", 0, &_lock);
Grid<Vec3> &vorticity = *_args.getPtr<Grid<Vec3>>("vorticity", 1, &_lock);
Grid<Real> *norm = _args.getPtrOpt<Grid<Real>>("norm", 2, NULL, &_lock);
_retval = getPyNone();
computeVorticity(vel, vorticity, norm);
_args.check();
}
pbFinalizePlugin(parent, "computeVorticity", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("computeVorticity", e.what());
return 0;
}
}
static const Pb::Register _RP_computeVorticity("", "computeVorticity", _W_8);
extern "C" {
void PbRegister_computeVorticity()
{
KEEP_UNUSED(_RP_computeVorticity);
}
}
// note - very similar to KnComputeProductionStrain, but for use as wavelet turb weighting
struct KnComputeStrainRateMag : public KernelBase {
KnComputeStrainRateMag(const MACGrid &vel, const Grid<Vec3> &velCenter, Grid<Real> &prod)
: KernelBase(&vel, 1), vel(vel), velCenter(velCenter), prod(prod)
{
runMessage();
run();
}
inline void op(
int i, int j, int k, const MACGrid &vel, const Grid<Vec3> &velCenter, Grid<Real> &prod) const
{
// compute Sij = 1/2 * (dU_i/dx_j + dU_j/dx_i)
Vec3 diag = Vec3(vel(i + 1, j, k).x, vel(i, j + 1, k).y, 0.) - vel(i, j, k);
if (vel.is3D())
diag[2] += vel(i, j, k + 1).z;
else
diag[2] = 0.;
Vec3 ux = 0.5 * (velCenter(i + 1, j, k) - velCenter(i - 1, j, k));
Vec3 uy = 0.5 * (velCenter(i, j + 1, k) - velCenter(i, j - 1, k));
Vec3 uz;
if (vel.is3D())
uz = 0.5 * (velCenter(i, j, k + 1) - velCenter(i, j, k - 1));
Real S12 = 0.5 * (ux.y + uy.x);
Real S13 = 0.5 * (ux.z + uz.x);
Real S23 = 0.5 * (uy.z + uz.y);
Real S2 = square(diag.x) + square(diag.y) + square(diag.z) + 2.0 * square(S12) +
2.0 * square(S13) + 2.0 * square(S23);
prod(i, j, k) = S2;
}
inline const MACGrid &getArg0()
{
return vel;
}
typedef MACGrid type0;
inline const Grid<Vec3> &getArg1()
{
return velCenter;
}
typedef Grid<Vec3> type1;
inline Grid<Real> &getArg2()
{
return prod;
}
typedef Grid<Real> type2;
void runMessage()
{
debMsg("Executing kernel KnComputeStrainRateMag ", 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, vel, velCenter, prod);
}
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, vel, velCenter, prod);
}
}
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 MACGrid &vel;
const Grid<Vec3> &velCenter;
Grid<Real> &prod;
};
void computeStrainRateMag(const MACGrid &vel, Grid<Real> &mag)
{
Grid<Vec3> velCenter(vel.getParent());
GetCentered(velCenter, vel);
KnComputeStrainRateMag(vel, velCenter, mag);
}
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, "computeStrainRateMag", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
const MACGrid &vel = *_args.getPtr<MACGrid>("vel", 0, &_lock);
Grid<Real> &mag = *_args.getPtr<Grid<Real>>("mag", 1, &_lock);
_retval = getPyNone();
computeStrainRateMag(vel, mag);
_args.check();
}
pbFinalizePlugin(parent, "computeStrainRateMag", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("computeStrainRateMag", e.what());
return 0;
}
}
static const Pb::Register _RP_computeStrainRateMag("", "computeStrainRateMag", _W_9);
extern "C" {
void PbRegister_computeStrainRateMag()
{
KEEP_UNUSED(_RP_computeStrainRateMag);
}
}
// extrapolate a real grid into a flagged region (based on initial flags)
// by default extrapolates from fluid to obstacle cells
template<class T>
void extrapolSimpleFlagsHelper(const FlagGrid &flags,
Grid<T> &val,
int distance = 4,
int flagFrom = FlagGrid::TypeFluid,
int flagTo = FlagGrid::TypeObstacle)
{
Grid<int> tmp(flags.getParent());
int dim = (flags.is3D() ? 3 : 2);
const Vec3i nb[6] = {Vec3i(1, 0, 0),
Vec3i(-1, 0, 0),
Vec3i(0, 1, 0),
Vec3i(0, -1, 0),
Vec3i(0, 0, 1),
Vec3i(0, 0, -1)};
// remove all fluid cells (set to 1)
tmp.clear();
bool foundTarget = false;
FOR_IJK_BND(flags, 0)
{
if (flags(i, j, k) & flagFrom)
tmp(Vec3i(i, j, k)) = 1;
if (!foundTarget && (flags(i, j, k) & flagTo))
foundTarget = true;
}
// optimization, skip extrapolation if we dont have any cells to extrapolate to
if (!foundTarget) {
debMsg("No target cells found, skipping extrapolation", 1);
return;
}
// extrapolate for given distance
for (int d = 1; d < 1 + distance; ++d) {
// TODO, parallelize
FOR_IJK_BND(flags, 1)
{
if (tmp(i, j, k) != 0)
continue;
if (!(flags(i, j, k) & flagTo))
continue;
// copy from initialized neighbors
Vec3i p(i, j, k);
int nbs = 0;
T avgVal = 0.;
for (int n = 0; n < 2 * dim; ++n) {
if (tmp(p + nb[n]) == d) {
avgVal += val(p + nb[n]);
nbs++;
}
}
if (nbs > 0) {
tmp(p) = d + 1;
val(p) = avgVal / nbs;
}
}
} // distance
}
void extrapolateSimpleFlags(const FlagGrid &flags,
GridBase *val,
int distance = 4,
int flagFrom = FlagGrid::TypeFluid,
int flagTo = FlagGrid::TypeObstacle)
{
if (val->getType() & GridBase::TypeReal) {
extrapolSimpleFlagsHelper<Real>(flags, *((Grid<Real> *)val), distance, flagFrom, flagTo);
}
else if (val->getType() & GridBase::TypeInt) {
extrapolSimpleFlagsHelper<int>(flags, *((Grid<int> *)val), distance, flagFrom, flagTo);
}
else if (val->getType() & GridBase::TypeVec3) {
extrapolSimpleFlagsHelper<Vec3>(flags, *((Grid<Vec3> *)val), distance, flagFrom, flagTo);
}
else
errMsg("extrapolateSimpleFlags: Grid Type is not supported (only int, Real, Vec3)");
}
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, "extrapolateSimpleFlags", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
GridBase *val = _args.getPtr<GridBase>("val", 1, &_lock);
int distance = _args.getOpt<int>("distance", 2, 4, &_lock);
int flagFrom = _args.getOpt<int>("flagFrom", 3, FlagGrid::TypeFluid, &_lock);
int flagTo = _args.getOpt<int>("flagTo", 4, FlagGrid::TypeObstacle, &_lock);
_retval = getPyNone();
extrapolateSimpleFlags(flags, val, distance, flagFrom, flagTo);
_args.check();
}
pbFinalizePlugin(parent, "extrapolateSimpleFlags", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("extrapolateSimpleFlags", e.what());
return 0;
}
}
static const Pb::Register _RP_extrapolateSimpleFlags("", "extrapolateSimpleFlags", _W_10);
extern "C" {
void PbRegister_extrapolateSimpleFlags()
{
KEEP_UNUSED(_RP_extrapolateSimpleFlags);
}
}
//! convert vel to a centered grid, then compute its curl
void getCurl(const MACGrid &vel, Grid<Real> &vort, int comp)
{
Grid<Vec3> velCenter(vel.getParent()), curl(vel.getParent());
GetCentered(velCenter, vel);
CurlOp(velCenter, curl);
GetComponent(curl, vort, comp);
}
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, "getCurl", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
const MACGrid &vel = *_args.getPtr<MACGrid>("vel", 0, &_lock);
Grid<Real> &vort = *_args.getPtr<Grid<Real>>("vort", 1, &_lock);
int comp = _args.get<int>("comp", 2, &_lock);
_retval = getPyNone();
getCurl(vel, vort, comp);
_args.check();
}
pbFinalizePlugin(parent, "getCurl", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("getCurl", e.what());
return 0;
}
}
static const Pb::Register _RP_getCurl("", "getCurl", _W_11);
extern "C" {
void PbRegister_getCurl()
{
KEEP_UNUSED(_RP_getCurl);
}
}
} // namespace Manta