Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
# SPDX-FileCopyrightText: 2019 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
add_definitions(-DWITH_FLUID=1)
if(WITH_OPENVDB)
add_definitions(-DOPENVDB=1)
else()
add_definitions(-DOPENVDB=0)
endif()
if(WIN32)
# Some files in `./extern` are being included which brings up a bunch of
# "unreferenced formal parameter" warnings.
# So restore warn C4100 (unreferenced formal parameter) back to w4
remove_c_and_cxx_flag("/w34100")
endif()
set(INC
extern
intern/strings
)
# Python is always required
add_definitions(-DWITH_PYTHON)
set(INC_SYS
../../extern/mantaflow/helper/util
../../extern/mantaflow/helper/pwrapper
../../extern/mantaflow/preprocessed
)
set(SRC
intern/manta_python_API.cpp
intern/manta_fluid_API.cpp
intern/MANTA_main.cpp
extern/manta_python_API.h
extern/manta_fluid_API.h
intern/MANTA_main.h
intern/strings/fluid_script.h
intern/strings/smoke_script.h
intern/strings/liquid_script.h
)
set(LIB
PRIVATE bf::blenlib
PRIVATE bf::dna
PRIVATE bf::intern::guardedalloc
PRIVATE bf::dependencies::optional::openvdb
PRIVATE bf::dependencies::optional::tbb
extern_mantaflow
PRIVATE bf::dependencies::optional::python
PRIVATE bf::dependencies::zlib
)
blender_add_lib(bf_intern_mantaflow "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@@ -0,0 +1,198 @@
/* SPDX-FileCopyrightText: 2016 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_mantaflow
*/
#include <cstddef>
namespace blender {
struct MANTA;
/* Fluid functions */
struct MANTA *manta_init(int *res, struct FluidModifierData *fmd);
void manta_free(struct MANTA *fluid);
bool manta_ensure_obstacle(struct MANTA *fluid, struct FluidModifierData *fmd);
bool manta_ensure_guiding(struct MANTA *fluid, struct FluidModifierData *fmd);
bool manta_ensure_invelocity(struct MANTA *fluid, struct FluidModifierData *fmd);
bool manta_ensure_outflow(struct MANTA *fluid, struct FluidModifierData *fmd);
bool manta_write_config(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
bool manta_write_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
bool manta_write_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
bool manta_read_config(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
bool manta_read_data(struct MANTA *fluid,
struct FluidModifierData *fmd,
int framenr,
bool resumable);
bool manta_read_noise(struct MANTA *fluid,
struct FluidModifierData *fmd,
int framenr,
bool resumable);
bool manta_read_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
bool manta_read_particles(struct MANTA *fluid,
struct FluidModifierData *fmd,
int framenr,
bool resumable);
bool manta_read_guiding(struct MANTA *fluid,
struct FluidModifierData *fmd,
int framenr,
bool sourceDomain);
bool manta_bake_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
bool manta_bake_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
bool manta_bake_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
bool manta_bake_particles(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
bool manta_bake_guiding(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
bool manta_has_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
bool manta_has_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
bool manta_has_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
bool manta_has_particles(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
bool manta_has_guiding(struct MANTA *fluid,
struct FluidModifierData *fmd,
int framenr,
bool domain);
void manta_update_variables(struct MANTA *fluid, struct FluidModifierData *fmd);
int manta_get_frame(struct MANTA *fluid);
float manta_get_timestep(struct MANTA *fluid);
void manta_adapt_timestep(struct MANTA *fluid);
bool manta_needs_realloc(struct MANTA *fluid, struct FluidModifierData *fmd);
void manta_update_pointers(struct MANTA *fluid, struct FluidModifierData *fmd, bool flush);
/* Fluid accessors */
size_t manta_get_index(int x, int max_x, int y, int max_y, int z /* , int max_z */);
size_t manta_get_index2d(int x, int max_x, int y /* , int max_y, int z, int max_z */);
float *manta_get_velocity_x(struct MANTA *fluid);
float *manta_get_velocity_y(struct MANTA *fluid);
float *manta_get_velocity_z(struct MANTA *fluid);
float *manta_get_ob_velocity_x(struct MANTA *fluid);
float *manta_get_ob_velocity_y(struct MANTA *fluid);
float *manta_get_ob_velocity_z(struct MANTA *fluid);
float *manta_get_guide_velocity_x(struct MANTA *fluid);
float *manta_get_guide_velocity_y(struct MANTA *fluid);
float *manta_get_guide_velocity_z(struct MANTA *fluid);
float *manta_get_in_velocity_x(struct MANTA *fluid);
float *manta_get_in_velocity_y(struct MANTA *fluid);
float *manta_get_in_velocity_z(struct MANTA *fluid);
float *manta_get_force_x(struct MANTA *fluid);
float *manta_get_force_y(struct MANTA *fluid);
float *manta_get_force_z(struct MANTA *fluid);
float *manta_get_phiguide_in(struct MANTA *fluid);
float *manta_get_num_obstacle(struct MANTA *fluid);
float *manta_get_num_guide(struct MANTA *fluid);
int manta_get_res_x(struct MANTA *fluid);
int manta_get_res_y(struct MANTA *fluid);
int manta_get_res_z(struct MANTA *fluid);
float *manta_get_phi_in(struct MANTA *fluid);
float *manta_get_phistatic_in(struct MANTA *fluid);
float *manta_get_phiobs_in(struct MANTA *fluid);
float *manta_get_phiobsstatic_in(struct MANTA *fluid);
float *manta_get_phiout_in(struct MANTA *fluid);
float *manta_get_phioutstatic_in(struct MANTA *fluid);
float *manta_get_phi(struct MANTA *fluid);
float *manta_get_pressure(struct MANTA *fluid);
/* Smoke functions */
bool manta_smoke_export_script(struct MANTA *smoke, struct FluidModifierData *fmd);
void manta_smoke_get_rgba(struct MANTA *smoke, float *data, int sequential);
void manta_noise_get_rgba(struct MANTA *smoke, float *data, int sequential);
void manta_smoke_get_rgba_fixed_color(struct MANTA *smoke,
float color[3],
float *data,
int sequential);
void manta_noise_get_rgba_fixed_color(struct MANTA *smoke,
float color[3],
float *data,
int sequential);
bool manta_smoke_ensure_heat(struct MANTA *smoke, struct FluidModifierData *fmd);
bool manta_smoke_ensure_fire(struct MANTA *smoke, struct FluidModifierData *fmd);
bool manta_smoke_ensure_colors(struct MANTA *smoke, struct FluidModifierData *fmd);
/* Smoke accessors */
float *manta_smoke_get_density(struct MANTA *smoke);
float *manta_smoke_get_fuel(struct MANTA *smoke);
float *manta_smoke_get_react(struct MANTA *smoke);
float *manta_smoke_get_heat(struct MANTA *smoke);
float *manta_smoke_get_flame(struct MANTA *smoke);
float *manta_smoke_get_shadow(struct MANTA *smoke);
float *manta_smoke_get_color_r(struct MANTA *smoke);
float *manta_smoke_get_color_g(struct MANTA *smoke);
float *manta_smoke_get_color_b(struct MANTA *smoke);
int *manta_smoke_get_flags(struct MANTA *smoke);
float *manta_smoke_get_density_in(struct MANTA *smoke);
float *manta_smoke_get_heat_in(struct MANTA *smoke);
float *manta_smoke_get_color_r_in(struct MANTA *smoke);
float *manta_smoke_get_color_g_in(struct MANTA *smoke);
float *manta_smoke_get_color_b_in(struct MANTA *smoke);
float *manta_smoke_get_fuel_in(struct MANTA *smoke);
float *manta_smoke_get_react_in(struct MANTA *smoke);
float *manta_smoke_get_emission_in(struct MANTA *smoke);
bool manta_smoke_has_heat(struct MANTA *smoke);
bool manta_smoke_has_fuel(struct MANTA *smoke);
bool manta_smoke_has_colors(struct MANTA *smoke);
float *manta_noise_get_density(struct MANTA *smoke);
float *manta_noise_get_fuel(struct MANTA *smoke);
float *manta_noise_get_react(struct MANTA *smoke);
float *manta_noise_get_color_r(struct MANTA *smoke);
float *manta_noise_get_color_g(struct MANTA *smoke);
float *manta_noise_get_color_b(struct MANTA *smoke);
float *manta_noise_get_texture_u(struct MANTA *smoke);
float *manta_noise_get_texture_v(struct MANTA *smoke);
float *manta_noise_get_texture_w(struct MANTA *smoke);
float *manta_noise_get_texture_u2(struct MANTA *smoke);
float *manta_noise_get_texture_v2(struct MANTA *smoke);
float *manta_noise_get_texture_w2(struct MANTA *smoke);
float *manta_noise_get_flame(struct MANTA *smoke);
bool manta_noise_has_fuel(struct MANTA *smoke);
bool manta_noise_has_colors(struct MANTA *smoke);
void manta_noise_get_res(struct MANTA *smoke, int *res);
int manta_noise_get_cells(struct MANTA *smoke);
/* Liquid functions */
bool manta_liquid_export_script(struct MANTA *liquid, struct FluidModifierData *fmd);
bool manta_liquid_ensure_sndparts(struct MANTA *liquid, struct FluidModifierData *fmd);
/* Liquid accessors */
int manta_liquid_get_particle_res_x(struct MANTA *liquid);
int manta_liquid_get_particle_res_y(struct MANTA *liquid);
int manta_liquid_get_particle_res_z(struct MANTA *liquid);
int manta_liquid_get_mesh_res_x(struct MANTA *liquid);
int manta_liquid_get_mesh_res_y(struct MANTA *liquid);
int manta_liquid_get_mesh_res_z(struct MANTA *liquid);
int manta_liquid_get_particle_upres(struct MANTA *liquid);
int manta_liquid_get_mesh_upres(struct MANTA *liquid);
int manta_liquid_get_num_verts(struct MANTA *liquid);
int manta_liquid_get_num_normals(struct MANTA *liquid);
int manta_liquid_get_num_triangles(struct MANTA *liquid);
float manta_liquid_get_vertex_x_at(struct MANTA *liquid, int i);
float manta_liquid_get_vertex_y_at(struct MANTA *liquid, int i);
float manta_liquid_get_vertex_z_at(struct MANTA *liquid, int i);
float manta_liquid_get_normal_x_at(struct MANTA *liquid, int i);
float manta_liquid_get_normal_y_at(struct MANTA *liquid, int i);
float manta_liquid_get_normal_z_at(struct MANTA *liquid, int i);
int manta_liquid_get_triangle_x_at(struct MANTA *liquid, int i);
int manta_liquid_get_triangle_y_at(struct MANTA *liquid, int i);
int manta_liquid_get_triangle_z_at(struct MANTA *liquid, int i);
float manta_liquid_get_vertvel_x_at(struct MANTA *liquid, int i);
float manta_liquid_get_vertvel_y_at(struct MANTA *liquid, int i);
float manta_liquid_get_vertvel_z_at(struct MANTA *liquid, int i);
int manta_liquid_get_num_flip_particles(struct MANTA *liquid);
int manta_liquid_get_num_snd_particles(struct MANTA *liquid);
int manta_liquid_get_flip_particle_flag_at(struct MANTA *liquid, int i);
int manta_liquid_get_snd_particle_flag_at(struct MANTA *liquid, int i);
float manta_liquid_get_flip_particle_position_x_at(struct MANTA *liquid, int i);
float manta_liquid_get_flip_particle_position_y_at(struct MANTA *liquid, int i);
float manta_liquid_get_flip_particle_position_z_at(struct MANTA *liquid, int i);
float manta_liquid_get_flip_particle_velocity_x_at(struct MANTA *liquid, int i);
float manta_liquid_get_flip_particle_velocity_y_at(struct MANTA *liquid, int i);
float manta_liquid_get_flip_particle_velocity_z_at(struct MANTA *liquid, int i);
float manta_liquid_get_snd_particle_position_x_at(struct MANTA *liquid, int i);
float manta_liquid_get_snd_particle_position_y_at(struct MANTA *liquid, int i);
float manta_liquid_get_snd_particle_position_z_at(struct MANTA *liquid, int i);
float manta_liquid_get_snd_particle_velocity_x_at(struct MANTA *liquid, int i);
float manta_liquid_get_snd_particle_velocity_y_at(struct MANTA *liquid, int i);
float manta_liquid_get_snd_particle_velocity_z_at(struct MANTA *liquid, int i);
} // namespace blender

View File

@@ -0,0 +1,24 @@
/* SPDX-FileCopyrightText: 2016 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_mantaflow
*/
#ifndef MANTA_PYTHON_API_H
#define MANTA_PYTHON_API_H
#include <Python.h>
#ifdef __cplusplus
extern "C" {
#endif
PyObject *Manta_initPython(void);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,877 @@
/* SPDX-FileCopyrightText: 2016 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_mantaflow
*/
#pragma once
#include <atomic>
#include <cassert>
#include <string>
#include <unordered_map>
#include <vector>
using std::atomic;
using std::string;
using std::unordered_map;
using std::vector;
namespace blender {
struct MANTA {
public:
MANTA(int *res, struct FluidModifierData *fmd);
virtual ~MANTA();
/* Mirroring Mantaflow structures for particle data (pVel also used for mesh vert vels). */
struct pData {
float pos[3];
int flag;
};
struct pVel {
float pos[3];
};
/* Mirroring Mantaflow structures for meshes. */
struct Node {
int flags;
float pos[3], normal[3];
};
struct Triangle {
int c[3];
int flags;
};
/* Grid initialization functions. */
bool initHeat(struct FluidModifierData *fmd = nullptr);
bool initFire(struct FluidModifierData *fmd = nullptr);
bool initColors(struct FluidModifierData *fmd = nullptr);
bool initFireHigh(struct FluidModifierData *fmd = nullptr);
bool initColorsHigh(struct FluidModifierData *fmd = nullptr);
bool initLiquid(FluidModifierData *fmd = nullptr);
bool initLiquidMesh(FluidModifierData *fmd = nullptr);
bool initLiquidViscosity(FluidModifierData *fmd = nullptr);
bool initObstacle(FluidModifierData *fmd = nullptr);
bool initCurvature(FluidModifierData *fmd = nullptr);
bool initGuiding(FluidModifierData *fmd = nullptr);
bool initFractions(FluidModifierData *fmd = nullptr);
bool initInVelocity(FluidModifierData *fmd = nullptr);
bool initOutflow(FluidModifierData *fmd = nullptr);
bool initSndParts(FluidModifierData *fmd = nullptr);
bool initLiquidSndParts(FluidModifierData *fmd = nullptr);
/* Pointer transfer: Mantaflow -> Blender. Use flush to reset all pointers to nullptr. */
void updatePointers(FluidModifierData *fmd, bool flush = false);
/* Write cache. */
bool writeConfiguration(FluidModifierData *fmd, int framenr);
bool writeData(FluidModifierData *fmd, int framenr);
bool writeNoise(FluidModifierData *fmd, int framenr);
/* Write calls for mesh and particles were left in bake calls for now. */
/* Read cache (via Python). */
bool readConfiguration(FluidModifierData *fmd, int framenr);
bool readData(FluidModifierData *fmd, int framenr, bool resumable);
bool readNoise(FluidModifierData *fmd, int framenr, bool resumable);
bool readMesh(FluidModifierData *fmd, int framenr);
bool readParticles(FluidModifierData *fmd, int framenr, bool resumable);
bool readGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain);
/* Propagate variable changes from RNA to Python. */
bool updateVariables(FluidModifierData *fmd);
/* Bake cache. */
bool bakeData(FluidModifierData *fmd, int framenr);
bool bakeNoise(FluidModifierData *fmd, int framenr);
bool bakeMesh(FluidModifierData *fmd, int framenr);
bool bakeParticles(FluidModifierData *fmd, int framenr);
bool bakeGuiding(FluidModifierData *fmd, int framenr);
/* IO for Mantaflow scene script. */
bool exportSmokeScript(struct FluidModifierData *fmd);
bool exportLiquidScript(struct FluidModifierData *fmd);
/* Check cache status by frame. */
bool hasConfig(FluidModifierData *fmd, int framenr);
bool hasData(FluidModifierData *fmd, int framenr);
bool hasNoise(FluidModifierData *fmd, int framenr);
bool hasMesh(FluidModifierData *fmd, int framenr);
bool hasParticles(FluidModifierData *fmd, int framenr);
bool hasGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain);
size_t getTotalCells()
{
return mTotalCells;
}
size_t getTotalCellsHigh()
{
return mTotalCellsHigh;
}
bool usingNoise()
{
return mUsingNoise;
}
int getResX()
{
return mResX;
}
int getResY()
{
return mResY;
}
int getResZ()
{
return mResZ;
}
int getParticleResX()
{
return mResXParticle;
}
int getParticleResY()
{
return mResYParticle;
}
int getParticleResZ()
{
return mResZParticle;
}
int getMeshResX()
{
return mResXMesh;
}
int getMeshResY()
{
return mResYMesh;
}
int getMeshResZ()
{
return mResZMesh;
}
int getResXHigh()
{
return mResXNoise;
}
int getResYHigh()
{
return mResYNoise;
}
int getResZHigh()
{
return mResZNoise;
}
int getMeshUpres()
{
return mUpresMesh;
}
int getParticleUpres()
{
return mUpresParticle;
}
/* Smoke getters. */
float *getDensity()
{
return mDensity;
}
float *getHeat()
{
return mHeat;
}
float *getVelocityX()
{
return mVelocityX;
}
float *getVelocityY()
{
return mVelocityY;
}
float *getVelocityZ()
{
return mVelocityZ;
}
float *getObVelocityX()
{
return mObVelocityX;
}
float *getObVelocityY()
{
return mObVelocityY;
}
float *getObVelocityZ()
{
return mObVelocityZ;
}
float *getGuideVelocityX()
{
return mGuideVelocityX;
}
float *getGuideVelocityY()
{
return mGuideVelocityY;
}
float *getGuideVelocityZ()
{
return mGuideVelocityZ;
}
float *getInVelocityX()
{
return mInVelocityX;
}
float *getInVelocityY()
{
return mInVelocityY;
}
float *getInVelocityZ()
{
return mInVelocityZ;
}
float *getForceX()
{
return mForceX;
}
float *getForceY()
{
return mForceY;
}
float *getForceZ()
{
return mForceZ;
}
int *getFlags()
{
return mFlags;
}
float *getNumObstacle()
{
return mNumObstacle;
}
float *getNumGuide()
{
return mNumGuide;
}
float *getFlame()
{
return mFlame;
}
float *getFuel()
{
return mFuel;
}
float *getReact()
{
return mReact;
}
float *getColorR()
{
return mColorR;
}
float *getColorG()
{
return mColorG;
}
float *getColorB()
{
return mColorB;
}
float *getShadow()
{
return mShadow;
}
float *getDensityIn()
{
return mDensityIn;
}
float *getHeatIn()
{
return mHeatIn;
}
float *getColorRIn()
{
return mColorRIn;
}
float *getColorGIn()
{
return mColorGIn;
}
float *getColorBIn()
{
return mColorBIn;
}
float *getFuelIn()
{
return mFuelIn;
}
float *getReactIn()
{
return mReactIn;
}
float *getEmissionIn()
{
return mEmissionIn;
}
float *getDensityHigh()
{
return mDensityHigh;
}
float *getFlameHigh()
{
return mFlameHigh;
}
float *getFuelHigh()
{
return mFuelHigh;
}
float *getReactHigh()
{
return mReactHigh;
}
float *getColorRHigh()
{
return mColorRHigh;
}
float *getColorGHigh()
{
return mColorGHigh;
}
float *getColorBHigh()
{
return mColorBHigh;
}
float *getTextureU()
{
return mTextureU;
}
float *getTextureV()
{
return mTextureV;
}
float *getTextureW()
{
return mTextureW;
}
float *getTextureU2()
{
return mTextureU2;
}
float *getTextureV2()
{
return mTextureV2;
}
float *getTextureW2()
{
return mTextureW2;
}
float *getPhiIn()
{
return mPhiIn;
}
float *getPhiStaticIn()
{
return mPhiStaticIn;
}
float *getPhiObsIn()
{
return mPhiObsIn;
}
float *getPhiObsStaticIn()
{
return mPhiObsStaticIn;
}
float *getPhiGuideIn()
{
return mPhiGuideIn;
}
float *getPhiOutIn()
{
return mPhiOutIn;
}
float *getPhiOutStaticIn()
{
return mPhiOutStaticIn;
}
float *getPhi()
{
return mPhi;
}
float *getPressure()
{
return mPressure;
}
static atomic<int> solverID;
static int with_debug; /* On or off (1 or 0), also sets manta debug level. */
/* Mesh getters. */
int getNumVertices()
{
return (mMeshNodes && !mMeshNodes->empty()) ? mMeshNodes->size() : 0;
}
int getNumNormals()
{
return (mMeshNodes && !mMeshNodes->empty()) ? mMeshNodes->size() : 0;
}
int getNumTriangles()
{
return (mMeshTriangles && !mMeshTriangles->empty()) ? mMeshTriangles->size() : 0;
}
float getVertexXAt(int i)
{
assert(i >= 0);
if (mMeshNodes && !mMeshNodes->empty()) {
assert(i < mMeshNodes->size());
return (*mMeshNodes)[i].pos[0];
}
return 0.0f;
}
float getVertexYAt(int i)
{
assert(i >= 0);
if (mMeshNodes && !mMeshNodes->empty()) {
assert(i < mMeshNodes->size());
return (*mMeshNodes)[i].pos[1];
}
return 0.0f;
}
float getVertexZAt(int i)
{
assert(i >= 0);
if (mMeshNodes && !mMeshNodes->empty()) {
assert(i < mMeshNodes->size());
return (*mMeshNodes)[i].pos[2];
}
return 0.0f;
}
float getNormalXAt(int i)
{
assert(i >= 0);
if (mMeshNodes && !mMeshNodes->empty()) {
assert(i < mMeshNodes->size());
return (*mMeshNodes)[i].normal[0];
}
return 0.0f;
}
float getNormalYAt(int i)
{
assert(i >= 0);
if (mMeshNodes && !mMeshNodes->empty()) {
assert(i < mMeshNodes->size());
return (*mMeshNodes)[i].normal[1];
}
return 0.0f;
}
float getNormalZAt(int i)
{
assert(i >= 0);
if (mMeshNodes && !mMeshNodes->empty()) {
assert(i < mMeshNodes->size());
return (*mMeshNodes)[i].normal[2];
}
return 0.0f;
}
int getTriangleXAt(int i)
{
assert(i >= 0);
if (mMeshTriangles && !mMeshTriangles->empty()) {
assert(i < mMeshTriangles->size());
return (*mMeshTriangles)[i].c[0];
}
return 0;
}
int getTriangleYAt(int i)
{
assert(i >= 0);
if (mMeshTriangles && !mMeshTriangles->empty()) {
assert(i < mMeshTriangles->size());
return (*mMeshTriangles)[i].c[1];
}
return 0;
}
int getTriangleZAt(int i)
{
assert(i >= 0);
if (mMeshTriangles && !mMeshTriangles->empty()) {
assert(i < mMeshTriangles->size());
return (*mMeshTriangles)[i].c[2];
}
return 0;
}
float getVertVelXAt(int i)
{
assert(i >= 0);
if (mMeshVelocities && !mMeshVelocities->empty()) {
assert(i < mMeshVelocities->size());
return (*mMeshVelocities)[i].pos[0];
}
return 0.0f;
}
float getVertVelYAt(int i)
{
assert(i >= 0);
if (mMeshVelocities && !mMeshVelocities->empty()) {
assert(i < mMeshVelocities->size());
return (*mMeshVelocities)[i].pos[1];
}
return 0.0f;
}
float getVertVelZAt(int i)
{
assert(i >= 0);
if (mMeshVelocities && !mMeshVelocities->empty()) {
assert(i < mMeshVelocities->size());
return (*mMeshVelocities)[i].pos[2];
}
return 0.0f;
}
// Particle getters
int getFlipParticleFlagAt(int i)
{
assert(i >= 0);
if (mFlipParticleData && !mFlipParticleData->empty()) {
assert(i < mFlipParticleData->size());
return (*mFlipParticleData)[i].flag;
}
return 0;
}
int getSndParticleFlagAt(int i)
{
assert(i >= 0);
if (mParticleData && !mParticleData->empty()) {
assert(i < mParticleData->size());
return (*mParticleData)[i].flag;
}
return 0;
}
float getFlipParticlePositionXAt(int i)
{
assert(i >= 0);
if (mFlipParticleData && !mFlipParticleData->empty()) {
assert(i < mFlipParticleData->size());
return (*mFlipParticleData)[i].pos[0];
}
return 0.0f;
}
float getFlipParticlePositionYAt(int i)
{
assert(i >= 0);
if (mFlipParticleData && !mFlipParticleData->empty()) {
assert(i < mFlipParticleData->size());
return (*mFlipParticleData)[i].pos[1];
}
return 0.0f;
}
float getFlipParticlePositionZAt(int i)
{
assert(i >= 0);
if (mFlipParticleData && !mFlipParticleData->empty()) {
assert(i < mFlipParticleData->size());
return (*mFlipParticleData)[i].pos[2];
}
return 0.0f;
}
float getSndParticlePositionXAt(int i)
{
assert(i >= 0);
if (mParticleData && !mParticleData->empty()) {
assert(i < mParticleData->size());
return (*mParticleData)[i].pos[0];
}
return 0.0f;
}
float getSndParticlePositionYAt(int i)
{
assert(i >= 0);
if (mParticleData && !mParticleData->empty()) {
assert(i < mParticleData->size());
return (*mParticleData)[i].pos[1];
}
return 0.0f;
}
float getSndParticlePositionZAt(int i)
{
assert(i >= 0);
if (mParticleData && !mParticleData->empty()) {
assert(i < mParticleData->size());
return (*mParticleData)[i].pos[2];
}
return 0.0f;
}
float getFlipParticleVelocityXAt(int i)
{
assert(i >= 0);
if (mFlipParticleVelocity && !mFlipParticleVelocity->empty()) {
assert(i < mFlipParticleVelocity->size());
return (*mFlipParticleVelocity)[i].pos[0];
}
return 0.0f;
}
float getFlipParticleVelocityYAt(int i)
{
assert(i >= 0);
if (mFlipParticleVelocity && !mFlipParticleVelocity->empty()) {
assert(i < mFlipParticleVelocity->size());
return (*mFlipParticleVelocity)[i].pos[1];
}
return 0.0f;
}
float getFlipParticleVelocityZAt(int i)
{
assert(i >= 0);
if (mFlipParticleVelocity && !mFlipParticleVelocity->empty()) {
assert(i < mFlipParticleVelocity->size());
return (*mFlipParticleVelocity)[i].pos[2];
}
return 0.0f;
}
float getSndParticleVelocityXAt(int i)
{
assert(i >= 0);
if (mParticleVelocity && !mParticleVelocity->empty()) {
assert(i < mParticleVelocity->size());
return (*mParticleVelocity)[i].pos[0];
}
return 0.0f;
}
float getSndParticleVelocityYAt(int i)
{
assert(i >= 0);
if (mParticleVelocity && !mParticleVelocity->empty()) {
assert(i < mParticleVelocity->size());
return (*mParticleVelocity)[i].pos[1];
}
return 0.0f;
}
float getSndParticleVelocityZAt(int i)
{
assert(i >= 0);
if (mParticleVelocity && !mParticleVelocity->empty()) {
assert(i < mParticleVelocity->size());
return (*mParticleVelocity)[i].pos[2];
}
return 0.0f;
}
float *getFlipParticleData()
{
return (mFlipParticleData && !mFlipParticleData->empty()) ?
(float *)&mFlipParticleData->front() :
nullptr;
}
float *getSndParticleData()
{
return (mParticleData && !mParticleData->empty()) ? (float *)&mParticleData->front() : nullptr;
}
float *getFlipParticleVelocity()
{
return (mFlipParticleVelocity && !mFlipParticleVelocity->empty()) ?
(float *)&mFlipParticleVelocity->front() :
nullptr;
}
float *getSndParticleVelocity()
{
return (mParticleVelocity && !mParticleVelocity->empty()) ?
(float *)&mParticleVelocity->front() :
nullptr;
}
float *getSndParticleLife()
{
return (mParticleLife && !mParticleLife->empty()) ? (float *)&mParticleLife->front() : nullptr;
}
int getNumFlipParticles()
{
return (mFlipParticleData && !mFlipParticleData->empty()) ? mFlipParticleData->size() : 0;
}
int getNumSndParticles()
{
return (mParticleData && !mParticleData->empty()) ? mParticleData->size() : 0;
}
bool usingFlipFromFile()
{
return mFlipFromFile;
}
bool usingMeshFromFile()
{
return mMeshFromFile;
}
bool usingParticleFromFile()
{
return mParticlesFromFile;
}
/* Direct access to solver time attributes. */
int getFrame();
float getTimestep();
void adaptTimestep();
bool needsRealloc(FluidModifierData *fmd);
private:
/* Simulation constants. */
size_t mTotalCells = -1;
size_t mTotalCellsHigh = -1;
size_t mTotalCellsMesh = -1;
size_t mTotalCellsParticles = -1;
unordered_map<string, string> mRNAMap;
/* The ID of the solver objects will be incremented for every new object. */
const int mCurrentID;
bool mUsingHeat = false;
bool mUsingColors = false;
bool mUsingFire = false;
bool mUsingObstacle = false;
bool mUsingGuiding = false;
bool mUsingFractions = false;
bool mUsingInvel = false;
bool mUsingOutflow = false;
bool mUsingNoise = false;
bool mUsingMesh = false;
bool mUsingDiffusion = false;
bool mUsingViscosity = false;
bool mUsingMVel = false;
bool mUsingLiquid = false;
bool mUsingSmoke = false;
bool mUsingDrops = false;
bool mUsingBubbles = false;
bool mUsingFloats = false;
bool mUsingTracers = false;
bool mFlipFromFile = false;
bool mMeshFromFile = false;
bool mParticlesFromFile = false;
bool mSmokeFromFile = false;
bool mNoiseFromFile = false;
int mResX = -1;
int mResY = -1;
int mResZ = -1;
const int mMaxRes;
int mResXNoise = -1;
int mResYNoise = -1;
int mResZNoise = -1;
int mResXMesh = -1;
int mResYMesh = -1;
int mResZMesh = -1;
int mResXParticle = -1;
int mResYParticle = -1;
int mResZParticle = -1;
int *mResGuiding = nullptr;
int mUpresMesh = -1;
int mUpresParticle = -1;
/* Fluid grids. */
float *mVelocityX = nullptr;
float *mVelocityY = nullptr;
float *mVelocityZ = nullptr;
float *mObVelocityX = nullptr;
float *mObVelocityY = nullptr;
float *mObVelocityZ = nullptr;
float *mGuideVelocityX = nullptr;
float *mGuideVelocityY = nullptr;
float *mGuideVelocityZ = nullptr;
float *mInVelocityX = nullptr;
float *mInVelocityY = nullptr;
float *mInVelocityZ = nullptr;
float *mForceX = nullptr;
float *mForceY = nullptr;
float *mForceZ = nullptr;
int *mFlags = nullptr;
float *mNumObstacle = nullptr;
float *mNumGuide = nullptr;
float *mPressure = nullptr;
/* Smoke grids. */
float *mDensity = nullptr;
float *mHeat = nullptr;
float *mFlame = nullptr;
float *mFuel = nullptr;
float *mReact = nullptr;
float *mColorR = nullptr;
float *mColorG = nullptr;
float *mColorB = nullptr;
float *mShadow = nullptr;
float *mDensityIn = nullptr;
float *mHeatIn = nullptr;
float *mFuelIn = nullptr;
float *mReactIn = nullptr;
float *mEmissionIn = nullptr;
float *mColorRIn = nullptr;
float *mColorGIn = nullptr;
float *mColorBIn = nullptr;
float *mDensityHigh = nullptr;
float *mFlameHigh = nullptr;
float *mFuelHigh = nullptr;
float *mReactHigh = nullptr;
float *mColorRHigh = nullptr;
float *mColorGHigh = nullptr;
float *mColorBHigh = nullptr;
float *mTextureU = nullptr;
float *mTextureV = nullptr;
float *mTextureW = nullptr;
float *mTextureU2 = nullptr;
float *mTextureV2 = nullptr;
float *mTextureW2 = nullptr;
/* Liquid grids. */
float *mPhiIn = nullptr;
float *mPhiStaticIn = nullptr;
float *mPhiObsIn = nullptr;
float *mPhiObsStaticIn = nullptr;
float *mPhiGuideIn = nullptr;
float *mPhiOutIn = nullptr;
float *mPhiOutStaticIn = nullptr;
float *mPhi = nullptr;
/* Mesh fields. */
vector<Node> *mMeshNodes;
vector<Triangle> *mMeshTriangles;
vector<pVel> *mMeshVelocities;
/* Particle fields. */
vector<pData> *mFlipParticleData;
vector<pVel> *mFlipParticleVelocity;
vector<pData> *mParticleData;
vector<pVel> *mParticleVelocity;
vector<float> *mParticleLife;
void initializeRNAMap(struct FluidModifierData *fmd = nullptr);
bool initDomain(struct FluidModifierData *fmd = nullptr);
bool initNoise(struct FluidModifierData *fmd = nullptr);
bool initMesh(struct FluidModifierData *fmd = nullptr);
bool initSmoke(struct FluidModifierData *fmd = nullptr);
bool initSmokeNoise(struct FluidModifierData *fmd = nullptr);
void initializeMantaflow();
void terminateMantaflow();
bool runPythonString(vector<string> commands);
string getRealValue(const string &varName);
string parseLine(const string &line);
string parseScript(const string &setup_string, FluidModifierData *fmd = nullptr);
string getDirectory(struct FluidModifierData *fmd, string subdirectory);
string getFile(struct FluidModifierData *fmd,
string subdirectory,
string fname,
string extension,
int framenr);
};
} // namespace blender

View File

@@ -0,0 +1,759 @@
/* SPDX-FileCopyrightText: 2016 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_mantaflow
*/
#include "manta_fluid_API.h"
#include "MANTA_main.h"
namespace blender {
/* Fluid functions */
MANTA *manta_init(int *res, struct FluidModifierData *fmd)
{
return new MANTA(res, fmd);
}
void manta_free(MANTA *fluid)
{
delete fluid;
}
bool manta_ensure_obstacle(MANTA *fluid, struct FluidModifierData *fmd)
{
return fluid->initObstacle(fmd);
}
bool manta_ensure_guiding(MANTA *fluid, struct FluidModifierData *fmd)
{
return fluid->initGuiding(fmd);
}
bool manta_ensure_invelocity(MANTA *fluid, struct FluidModifierData *fmd)
{
return fluid->initInVelocity(fmd);
}
bool manta_ensure_outflow(MANTA *fluid, struct FluidModifierData *fmd)
{
return fluid->initOutflow(fmd);
}
bool manta_write_config(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
return fluid->writeConfiguration(fmd, framenr);
}
bool manta_write_data(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
return fluid->writeData(fmd, framenr);
}
bool manta_write_noise(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
return fluid->writeNoise(fmd, framenr);
}
bool manta_read_config(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
return fluid->readConfiguration(fmd, framenr);
}
bool manta_read_data(MANTA *fluid, FluidModifierData *fmd, int framenr, bool resumable)
{
return fluid->readData(fmd, framenr, resumable);
}
bool manta_read_noise(MANTA *fluid, FluidModifierData *fmd, int framenr, bool resumable)
{
return fluid->readNoise(fmd, framenr, resumable);
}
bool manta_read_mesh(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
return fluid->readMesh(fmd, framenr);
}
bool manta_read_particles(MANTA *fluid, FluidModifierData *fmd, int framenr, bool resumable)
{
return fluid->readParticles(fmd, framenr, resumable);
}
bool manta_read_guiding(MANTA *fluid, FluidModifierData *fmd, int framenr, bool sourceDomain)
{
return fluid->readGuiding(fmd, framenr, sourceDomain);
}
bool manta_bake_data(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
return fluid->bakeData(fmd, framenr);
}
bool manta_bake_noise(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
return fluid->bakeNoise(fmd, framenr);
}
bool manta_bake_mesh(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
return fluid->bakeMesh(fmd, framenr);
}
bool manta_bake_particles(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
return fluid->bakeParticles(fmd, framenr);
}
bool manta_bake_guiding(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
return fluid->bakeGuiding(fmd, framenr);
}
bool manta_has_data(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
return fluid->hasData(fmd, framenr);
}
bool manta_has_noise(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
return fluid->hasNoise(fmd, framenr);
}
bool manta_has_mesh(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
return fluid->hasMesh(fmd, framenr);
}
bool manta_has_particles(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
return fluid->hasParticles(fmd, framenr);
}
bool manta_has_guiding(MANTA *fluid, FluidModifierData *fmd, int framenr, bool domain)
{
return fluid->hasGuiding(fmd, framenr, domain);
}
void manta_update_variables(MANTA *fluid, FluidModifierData *fmd)
{
fluid->updateVariables(fmd);
}
int manta_get_frame(MANTA *fluid)
{
return fluid->getFrame();
}
float manta_get_timestep(MANTA *fluid)
{
return fluid->getTimestep();
}
void manta_adapt_timestep(MANTA *fluid)
{
fluid->adaptTimestep();
}
bool manta_needs_realloc(MANTA *fluid, FluidModifierData *fmd)
{
return fluid->needsRealloc(fmd);
}
void manta_update_pointers(struct MANTA *fluid, struct FluidModifierData *fmd, bool flush)
{
fluid->updatePointers(fmd, flush);
}
/* Fluid accessors */
size_t manta_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */)
{
return x + y * max_x + z * max_x * max_y;
}
size_t manta_get_index2d(int x, int max_x, int y /* , int max_y, int z, int max_z */)
{
return x + y * max_x;
}
float *manta_get_velocity_x(MANTA *fluid)
{
return fluid->getVelocityX();
}
float *manta_get_velocity_y(MANTA *fluid)
{
return fluid->getVelocityY();
}
float *manta_get_velocity_z(MANTA *fluid)
{
return fluid->getVelocityZ();
}
float *manta_get_ob_velocity_x(MANTA *fluid)
{
return fluid->getObVelocityX();
}
float *manta_get_ob_velocity_y(MANTA *fluid)
{
return fluid->getObVelocityY();
}
float *manta_get_ob_velocity_z(MANTA *fluid)
{
return fluid->getObVelocityZ();
}
float *manta_get_guide_velocity_x(MANTA *fluid)
{
return fluid->getGuideVelocityX();
}
float *manta_get_guide_velocity_y(MANTA *fluid)
{
return fluid->getGuideVelocityY();
}
float *manta_get_guide_velocity_z(MANTA *fluid)
{
return fluid->getGuideVelocityZ();
}
float *manta_get_in_velocity_x(MANTA *fluid)
{
return fluid->getInVelocityX();
}
float *manta_get_in_velocity_y(MANTA *fluid)
{
return fluid->getInVelocityY();
}
float *manta_get_in_velocity_z(MANTA *fluid)
{
return fluid->getInVelocityZ();
}
float *manta_get_force_x(MANTA *fluid)
{
return fluid->getForceX();
}
float *manta_get_force_y(MANTA *fluid)
{
return fluid->getForceY();
}
float *manta_get_force_z(MANTA *fluid)
{
return fluid->getForceZ();
}
float *manta_get_phiguide_in(MANTA *fluid)
{
return fluid->getPhiGuideIn();
}
float *manta_get_num_obstacle(MANTA *fluid)
{
return fluid->getNumObstacle();
}
float *manta_get_num_guide(MANTA *fluid)
{
return fluid->getNumGuide();
}
int manta_get_res_x(MANTA *fluid)
{
return fluid->getResX();
}
int manta_get_res_y(MANTA *fluid)
{
return fluid->getResY();
}
int manta_get_res_z(MANTA *fluid)
{
return fluid->getResZ();
}
float *manta_get_phi_in(MANTA *fluid)
{
return fluid->getPhiIn();
}
float *manta_get_phistatic_in(MANTA *fluid)
{
return fluid->getPhiStaticIn();
}
float *manta_get_phiobs_in(MANTA *fluid)
{
return fluid->getPhiObsIn();
}
float *manta_get_phiobsstatic_in(MANTA *fluid)
{
return fluid->getPhiObsStaticIn();
}
float *manta_get_phiout_in(MANTA *fluid)
{
return fluid->getPhiOutIn();
}
float *manta_get_phioutstatic_in(MANTA *fluid)
{
return fluid->getPhiOutStaticIn();
}
float *manta_get_phi(MANTA *fluid)
{
return fluid->getPhi();
}
float *manta_get_pressure(MANTA *fluid)
{
return fluid->getPressure();
}
/* Smoke functions */
bool manta_smoke_export_script(MANTA *smoke, FluidModifierData *fmd)
{
return smoke->exportSmokeScript(fmd);
}
static void get_rgba(const float *r,
const float *g,
const float *b,
const float *a,
int total_cells,
float *data,
int sequential)
{
int i;
/* Use offsets to map RGB grids to correct location in data grid. */
int m = 4, i_g = 1, i_b = 2, i_a = 3;
if (sequential) {
m = 1;
i_g *= total_cells;
i_b *= total_cells;
i_a *= total_cells;
}
for (i = 0; i < total_cells; i++) {
float alpha = a[i];
data[i * m] = r[i] * alpha;
data[i * m + i_g] = g[i] * alpha;
data[i * m + i_b] = b[i] * alpha;
data[i * m + i_a] = alpha;
}
}
void manta_smoke_get_rgba(MANTA *smoke, float *data, int sequential)
{
get_rgba(smoke->getColorR(),
smoke->getColorG(),
smoke->getColorB(),
smoke->getDensity(),
smoke->getTotalCells(),
data,
sequential);
}
void manta_noise_get_rgba(MANTA *smoke, float *data, int sequential)
{
get_rgba(smoke->getColorRHigh(),
smoke->getColorGHigh(),
smoke->getColorBHigh(),
smoke->getDensityHigh(),
smoke->getTotalCellsHigh(),
data,
sequential);
}
static void get_rgba_fixed_color(const float color[3],
int total_cells,
float *data,
int sequential)
{
int i;
int m = 4, i_g = 1, i_b = 2, i_a = 3;
if (sequential) {
m = 1;
i_g *= total_cells;
i_b *= total_cells;
i_a *= total_cells;
}
for (i = 0; i < total_cells; i++) {
data[i * m] = color[0];
data[i * m + i_g] = color[1];
data[i * m + i_b] = color[2];
data[i * m + i_a] = 1.0f;
}
}
void manta_smoke_get_rgba_fixed_color(MANTA *smoke, float color[3], float *data, int sequential)
{
get_rgba_fixed_color(color, smoke->getTotalCells(), data, sequential);
}
void manta_noise_get_rgba_fixed_color(MANTA *smoke, float color[3], float *data, int sequential)
{
get_rgba_fixed_color(color, smoke->getTotalCellsHigh(), data, sequential);
}
bool manta_smoke_ensure_heat(MANTA *smoke, struct FluidModifierData *fmd)
{
return smoke->initHeat(fmd);
}
bool manta_smoke_ensure_fire(MANTA *smoke, struct FluidModifierData *fmd)
{
bool result = smoke->initFire(fmd);
if (smoke->usingNoise()) {
result &= smoke->initFireHigh(fmd);
}
return result;
}
bool manta_smoke_ensure_colors(MANTA *smoke, struct FluidModifierData *fmd)
{
bool result = smoke->initColors(fmd);
if (smoke->usingNoise()) {
result &= smoke->initColorsHigh(fmd);
}
return result;
}
/* Smoke accessors */
float *manta_smoke_get_density(MANTA *smoke)
{
return smoke->getDensity();
}
float *manta_smoke_get_fuel(MANTA *smoke)
{
return smoke->getFuel();
}
float *manta_smoke_get_react(MANTA *smoke)
{
return smoke->getReact();
}
float *manta_smoke_get_heat(MANTA *smoke)
{
return smoke->getHeat();
}
float *manta_smoke_get_flame(MANTA *smoke)
{
return smoke->getFlame();
}
float *manta_smoke_get_shadow(MANTA *smoke)
{
return smoke->getShadow();
}
float *manta_smoke_get_color_r(MANTA *smoke)
{
return smoke->getColorR();
}
float *manta_smoke_get_color_g(MANTA *smoke)
{
return smoke->getColorG();
}
float *manta_smoke_get_color_b(MANTA *smoke)
{
return smoke->getColorB();
}
int *manta_smoke_get_flags(MANTA *smoke)
{
return smoke->getFlags();
}
float *manta_smoke_get_density_in(MANTA *smoke)
{
return smoke->getDensityIn();
}
float *manta_smoke_get_heat_in(MANTA *smoke)
{
return smoke->getHeatIn();
}
float *manta_smoke_get_color_r_in(MANTA *smoke)
{
return smoke->getColorRIn();
}
float *manta_smoke_get_color_g_in(MANTA *smoke)
{
return smoke->getColorGIn();
}
float *manta_smoke_get_color_b_in(MANTA *smoke)
{
return smoke->getColorBIn();
}
float *manta_smoke_get_fuel_in(MANTA *smoke)
{
return smoke->getFuelIn();
}
float *manta_smoke_get_react_in(MANTA *smoke)
{
return smoke->getReactIn();
}
float *manta_smoke_get_emission_in(MANTA *smoke)
{
return smoke->getEmissionIn();
}
bool manta_smoke_has_heat(MANTA *smoke)
{
return smoke->getHeat() != nullptr;
;
}
bool manta_smoke_has_fuel(MANTA *smoke)
{
return smoke->getFuel() != nullptr;
}
bool manta_smoke_has_colors(MANTA *smoke)
{
return smoke->getColorR() != nullptr && smoke->getColorG() != nullptr &&
smoke->getColorB() != nullptr;
}
float *manta_noise_get_density(MANTA *smoke)
{
return smoke->getDensityHigh();
}
float *manta_noise_get_fuel(MANTA *smoke)
{
return smoke->getFuelHigh();
}
float *manta_noise_get_react(MANTA *smoke)
{
return smoke->getReactHigh();
}
float *manta_noise_get_color_r(MANTA *smoke)
{
return smoke->getColorRHigh();
}
float *manta_noise_get_color_g(MANTA *smoke)
{
return smoke->getColorGHigh();
}
float *manta_noise_get_color_b(MANTA *smoke)
{
return smoke->getColorBHigh();
}
float *manta_noise_get_flame(MANTA *smoke)
{
return smoke->getFlameHigh();
}
float *manta_noise_get_texture_u(MANTA *smoke)
{
return smoke->getTextureU();
}
float *manta_noise_get_texture_v(MANTA *smoke)
{
return smoke->getTextureV();
}
float *manta_noise_get_texture_w(MANTA *smoke)
{
return smoke->getTextureW();
}
float *manta_noise_get_texture_u2(MANTA *smoke)
{
return smoke->getTextureU2();
}
float *manta_noise_get_texture_v2(MANTA *smoke)
{
return smoke->getTextureV2();
}
float *manta_noise_get_texture_w2(MANTA *smoke)
{
return smoke->getTextureW2();
}
bool manta_noise_has_fuel(MANTA *smoke)
{
return smoke->getFuelHigh() != nullptr;
}
bool manta_noise_has_colors(MANTA *smoke)
{
return smoke->getColorRHigh() != nullptr && smoke->getColorGHigh() != nullptr &&
smoke->getColorBHigh() != nullptr;
;
}
void manta_noise_get_res(MANTA *smoke, int *res)
{
res[0] = smoke->getResXHigh();
res[1] = smoke->getResYHigh();
res[2] = smoke->getResZHigh();
}
int manta_noise_get_cells(MANTA *smoke)
{
return smoke->getResXHigh() * smoke->getResYHigh() * smoke->getResZHigh();
}
/* Liquid functions */
bool manta_liquid_export_script(MANTA *liquid, FluidModifierData *fmd)
{
return liquid->exportLiquidScript(fmd);
}
bool manta_liquid_ensure_sndparts(MANTA *liquid, struct FluidModifierData *fmd)
{
return liquid->initLiquidSndParts(fmd);
}
/* Liquid accessors */
int manta_liquid_get_particle_res_x(MANTA *liquid)
{
return liquid->getParticleResX();
}
int manta_liquid_get_particle_res_y(MANTA *liquid)
{
return liquid->getParticleResY();
}
int manta_liquid_get_particle_res_z(MANTA *liquid)
{
return liquid->getParticleResZ();
}
int manta_liquid_get_mesh_res_x(MANTA *liquid)
{
return liquid->getMeshResX();
}
int manta_liquid_get_mesh_res_y(MANTA *liquid)
{
return liquid->getMeshResY();
}
int manta_liquid_get_mesh_res_z(MANTA *liquid)
{
return liquid->getMeshResZ();
}
int manta_liquid_get_particle_upres(MANTA *liquid)
{
return liquid->getParticleUpres();
}
int manta_liquid_get_mesh_upres(MANTA *liquid)
{
return liquid->getMeshUpres();
}
int manta_liquid_get_num_verts(MANTA *liquid)
{
return liquid->getNumVertices();
}
int manta_liquid_get_num_normals(MANTA *liquid)
{
return liquid->getNumNormals();
}
int manta_liquid_get_num_triangles(MANTA *liquid)
{
return liquid->getNumTriangles();
}
float manta_liquid_get_vertex_x_at(MANTA *liquid, int i)
{
return liquid->getVertexXAt(i);
}
float manta_liquid_get_vertex_y_at(MANTA *liquid, int i)
{
return liquid->getVertexYAt(i);
}
float manta_liquid_get_vertex_z_at(MANTA *liquid, int i)
{
return liquid->getVertexZAt(i);
}
float manta_liquid_get_normal_x_at(MANTA *liquid, int i)
{
return liquid->getNormalXAt(i);
}
float manta_liquid_get_normal_y_at(MANTA *liquid, int i)
{
return liquid->getNormalYAt(i);
}
float manta_liquid_get_normal_z_at(MANTA *liquid, int i)
{
return liquid->getNormalZAt(i);
}
int manta_liquid_get_triangle_x_at(MANTA *liquid, int i)
{
return liquid->getTriangleXAt(i);
}
int manta_liquid_get_triangle_y_at(MANTA *liquid, int i)
{
return liquid->getTriangleYAt(i);
}
int manta_liquid_get_triangle_z_at(MANTA *liquid, int i)
{
return liquid->getTriangleZAt(i);
}
float manta_liquid_get_vertvel_x_at(MANTA *liquid, int i)
{
return liquid->getVertVelXAt(i);
}
float manta_liquid_get_vertvel_y_at(MANTA *liquid, int i)
{
return liquid->getVertVelYAt(i);
}
float manta_liquid_get_vertvel_z_at(MANTA *liquid, int i)
{
return liquid->getVertVelZAt(i);
}
int manta_liquid_get_num_flip_particles(MANTA *liquid)
{
return liquid->getNumFlipParticles();
}
int manta_liquid_get_num_snd_particles(MANTA *liquid)
{
return liquid->getNumSndParticles();
}
int manta_liquid_get_flip_particle_flag_at(MANTA *liquid, int i)
{
return liquid->getFlipParticleFlagAt(i);
}
int manta_liquid_get_snd_particle_flag_at(MANTA *liquid, int i)
{
return liquid->getSndParticleFlagAt(i);
}
float manta_liquid_get_flip_particle_position_x_at(MANTA *liquid, int i)
{
return liquid->getFlipParticlePositionXAt(i);
}
float manta_liquid_get_flip_particle_position_y_at(MANTA *liquid, int i)
{
return liquid->getFlipParticlePositionYAt(i);
}
float manta_liquid_get_flip_particle_position_z_at(MANTA *liquid, int i)
{
return liquid->getFlipParticlePositionZAt(i);
}
float manta_liquid_get_flip_particle_velocity_x_at(MANTA *liquid, int i)
{
return liquid->getFlipParticleVelocityXAt(i);
}
float manta_liquid_get_flip_particle_velocity_y_at(MANTA *liquid, int i)
{
return liquid->getFlipParticleVelocityYAt(i);
}
float manta_liquid_get_flip_particle_velocity_z_at(MANTA *liquid, int i)
{
return liquid->getFlipParticleVelocityZAt(i);
}
float manta_liquid_get_snd_particle_position_x_at(MANTA *liquid, int i)
{
return liquid->getSndParticlePositionXAt(i);
}
float manta_liquid_get_snd_particle_position_y_at(MANTA *liquid, int i)
{
return liquid->getSndParticlePositionYAt(i);
}
float manta_liquid_get_snd_particle_position_z_at(MANTA *liquid, int i)
{
return liquid->getSndParticlePositionZAt(i);
}
float manta_liquid_get_snd_particle_velocity_x_at(MANTA *liquid, int i)
{
return liquid->getSndParticleVelocityXAt(i);
}
float manta_liquid_get_snd_particle_velocity_y_at(MANTA *liquid, int i)
{
return liquid->getSndParticleVelocityYAt(i);
}
float manta_liquid_get_snd_particle_velocity_z_at(MANTA *liquid, int i)
{
return liquid->getSndParticleVelocityZAt(i);
}
} // namespace blender

View File

@@ -0,0 +1,15 @@
/* SPDX-FileCopyrightText: 2016 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_mantaflow
*/
#include "manta_python_API.h"
#include "manta.h"
PyObject *Manta_initPython(void)
{
return Pb::PyInit_manta_main();
}

View File

@@ -0,0 +1,828 @@
/* SPDX-FileCopyrightText: 2016 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_mantaflow
*/
#include <string>
//////////////////////////////////////////////////////////////////////
// LIBRARIES
//////////////////////////////////////////////////////////////////////
const std::string manta_import =
"\
from manta import *\n\
from math import inf\n\
import os.path, shutil, math, sys, gc, multiprocessing, platform, time\n\
\n\
withMPBake = False # Bake files asynchronously\n\
withMPSave = False # Save files asynchronously\n\
isWindows = platform.system() != 'Darwin' and platform.system() != 'Linux'\n\
# TODO(sebbas): Use this to simulate Windows multiprocessing (has default mode spawn)\n\
#try:\n\
# multiprocessing.set_start_method('spawn')\n\
#except:\n\
# pass\n";
//////////////////////////////////////////////////////////////////////
// DEBUG
//////////////////////////////////////////////////////////////////////
const std::string manta_debuglevel =
"\n\
def set_manta_debuglevel(level):\n\
setDebugLevel(level=level)\n # level 0 = mute all output from manta\n";
//////////////////////////////////////////////////////////////////////
// SOLVERS
//////////////////////////////////////////////////////////////////////
const std::string fluid_solver =
"\n\
mantaMsg('Solver base')\n\
s$ID$ = Solver(name='solver_base$ID$', gridSize=gs_s$ID$, dim=dim_s$ID$)\n";
const std::string fluid_solver_noise =
"\n\
mantaMsg('Solver noise')\n\
sn$ID$ = Solver(name='solver_noise$ID$', gridSize=gs_sn$ID$)\n";
const std::string fluid_solver_mesh =
"\n\
mantaMsg('Solver mesh')\n\
sm$ID$ = Solver(name='solver_mesh$ID$', gridSize=gs_sm$ID$)\n";
const std::string fluid_solver_particles =
"\n\
mantaMsg('Solver particles')\n\
sp$ID$ = Solver(name='solver_particles$ID$', gridSize=gs_sp$ID$)\n";
const std::string fluid_solver_guiding =
"\n\
mantaMsg('Solver guiding')\n\
sg$ID$ = Solver(name='solver_guiding$ID$', gridSize=gs_sg$ID$)\n";
const std::string fluid_solver_viscosity =
"\n\
mantaMsg('Solver viscosity')\n\
sv$ID$ = Solver(name='solver_viscosity$ID$', gridSize=gs_sv$ID$, dim=dim_s$ID$)\n";
//////////////////////////////////////////////////////////////////////
// VARIABLES
//////////////////////////////////////////////////////////////////////
const std::string fluid_variables =
"\n\
mantaMsg('Fluid variables')\n\
dim_s$ID$ = $SOLVER_DIM$\n\
res_s$ID$ = $RES$\n\
gravity_s$ID$ = vec3($GRAVITY_X$, $GRAVITY_Y$, $GRAVITY_Z$) # in SI unit (e.g. m/s^2)\n\
gs_s$ID$ = vec3($RESX$, $RESY$, $RESZ$)\n\
maxVel_s$ID$ = 0\n\
\n\
domainClosed_s$ID$ = $DOMAIN_CLOSED$\n\
boundConditions_s$ID$ = '$BOUND_CONDITIONS$'\n\
boundaryWidth_s$ID$ = $BOUNDARY_WIDTH$\n\
deleteInObstacle_s$ID$ = $DELETE_IN_OBSTACLE$\n\
\n\
using_smoke_s$ID$ = $USING_SMOKE$\n\
using_liquid_s$ID$ = $USING_LIQUID$\n\
using_noise_s$ID$ = $USING_NOISE$\n\
using_adaptTime_s$ID$ = $USING_ADAPTIVETIME$\n\
using_obstacle_s$ID$ = $USING_OBSTACLE$\n\
using_guiding_s$ID$ = $USING_GUIDING$\n\
using_fractions_s$ID$ = $USING_FRACTIONS$\n\
using_invel_s$ID$ = $USING_INVEL$\n\
using_outflow_s$ID$ = $USING_OUTFLOW$\n\
using_sndparts_s$ID$ = $USING_SNDPARTS$\n\
using_speedvectors_s$ID$ = $USING_SPEEDVECTORS$\n\
using_diffusion_s$ID$ = $USING_DIFFUSION$\n\
\n\
# Fluid time params\n\
timeScale_s$ID$ = $TIME_SCALE$\n\
timeTotal_s$ID$ = $TIME_TOTAL$\n\
timePerFrame_s$ID$ = $TIME_PER_FRAME$\n\
\n\
# In Blender fluid.c: frame_length = DT_DEFAULT * (25.0 / fps) * time_scale\n\
# with DT_DEFAULT = 0.1\n\
frameLength_s$ID$ = $FRAME_LENGTH$\n\
frameLengthUnscaled_s$ID$ = frameLength_s$ID$ / timeScale_s$ID$\n\
frameLengthRaw_s$ID$ = 0.1 * 25 # dt = 0.1 at 25 fps\n\
\n\
dt0_s$ID$ = $DT$\n\
cflCond_s$ID$ = $CFL$\n\
timestepsMin_s$ID$ = $TIMESTEPS_MIN$\n\
timestepsMax_s$ID$ = $TIMESTEPS_MAX$\n\
\n\
# Start and stop for simulation\n\
current_frame_s$ID$ = $CURRENT_FRAME$\n\
start_frame_s$ID$ = $START_FRAME$\n\
end_frame_s$ID$ = $END_FRAME$\n\
\n\
# Fluid diffusion / viscosity\n\
domainSize_s$ID$ = $FLUID_DOMAIN_SIZE$ # longest domain side in meters\n\
kinViscosity_s$ID$ = $FLUID_VISCOSITY$ / (domainSize_s$ID$*domainSize_s$ID$) # kinematic viscosity in m^2/s\n\
\n\
# Factors to convert Blender units to Manta units\n\
ratioMetersToRes_s$ID$ = float(domainSize_s$ID$) / float(res_s$ID$) # [meters / cells]\n\
mantaMsg('1 Mantaflow cell is ' + str(ratioMetersToRes_s$ID$) + ' Blender length units long.')\n\
\n\
ratioResToBLength_s$ID$ = float(res_s$ID$) / float(domainSize_s$ID$) # [cells / blength] (blength: cm, m, or km, ... )\n\
mantaMsg('1 Blender length unit is ' + str(ratioResToBLength_s$ID$) + ' Mantaflow cells long.')\n\
\n\
ratioBTimeToTimestep_s$ID$ = float(1) / float(frameLengthRaw_s$ID$) # the time within 1 blender time unit, see also fluid.c\n\
mantaMsg('1 Blender time unit is ' + str(ratioBTimeToTimestep_s$ID$) + ' Mantaflow time units long.')\n\
\n\
ratioFrameToFramelength_s$ID$ = float(1) / float(frameLengthUnscaled_s$ID$ ) # the time within 1 frame\n\
mantaMsg('frame / frameLength is ' + str(ratioFrameToFramelength_s$ID$) + ' Mantaflow time units long.')\n\
\n\
scaleAcceleration_s$ID$ = ratioResToBLength_s$ID$ * (ratioBTimeToTimestep_s$ID$**2)# [meters/btime^2] to [cells/timestep^2] (btime: sec, min, or h, ...)\n\
mantaMsg('scaleAcceleration is ' + str(scaleAcceleration_s$ID$))\n\
\n\
scaleSpeedFrames_s$ID$ = ratioResToBLength_s$ID$ * ratioFrameToFramelength_s$ID$ # [blength/frame] to [cells/frameLength]\n\
mantaMsg('scaleSpeed is ' + str(scaleSpeedFrames_s$ID$))\n\
\n\
gravity_s$ID$ *= scaleAcceleration_s$ID$ # scale from world acceleration to cell based acceleration\n\
\n\
# OpenVDB options\n\
vdbCompression_s$ID$ = $COMPRESSION_OPENVDB$\n\
vdbPrecision_s$ID$ = $PRECISION_OPENVDB$\n\
vdbClip_s$ID$ = $CLIP_OPENVDB$\n\
\n\
# Cache file names\n\
file_data_s$ID$ = '$NAME_DATA$'\n\
file_noise_s$ID$ = '$NAME_NOISE$'\n\
file_mesh_s$ID$ = '$NAME_MESH$'\n\
file_meshvel_s$ID$ = '$NAME_MESH$'\n\
file_particles_s$ID$ = '$NAME_PARTICLES$'\n\
file_guiding_s$ID$ = '$NAME_GUIDING$'";
const std::string fluid_variables_noise =
"\n\
mantaMsg('Fluid variables noise')\n\
upres_sn$ID$ = $NOISE_SCALE$\n\
gs_sn$ID$ = vec3(upres_sn$ID$*gs_s$ID$.x, upres_sn$ID$*gs_s$ID$.y, upres_sn$ID$*gs_s$ID$.z)\n";
const std::string fluid_variables_mesh =
"\n\
mantaMsg('Fluid variables mesh')\n\
upres_sm$ID$ = $MESH_SCALE$\n\
gs_sm$ID$ = vec3(upres_sm$ID$*gs_s$ID$.x, upres_sm$ID$*gs_s$ID$.y, upres_sm$ID$*gs_s$ID$.z)\n";
const std::string fluid_variables_particles =
"\n\
mantaMsg('Fluid variables particles')\n\
upres_sp$ID$ = $PARTICLE_SCALE$\n\
gs_sp$ID$ = vec3(upres_sp$ID$*gs_s$ID$.x, upres_sp$ID$*gs_s$ID$.y, upres_sp$ID$*gs_s$ID$.z)\n";
const std::string fluid_variables_guiding =
"\n\
mantaMsg('Fluid variables guiding')\n\
gs_sg$ID$ = vec3($GUIDING_RESX$, $GUIDING_RESY$, $GUIDING_RESZ$)\n\
\n\
alpha_sg$ID$ = $GUIDING_ALPHA$\n\
beta_sg$ID$ = $GUIDING_BETA$\n\
gamma_sg$ID$ = $GUIDING_FACTOR$\n\
tau_sg$ID$ = 1.0\n\
sigma_sg$ID$ = 0.99/tau_sg$ID$\n\
theta_sg$ID$ = 1.0\n";
const std::string fluid_variables_viscosity =
"\n\
gs_sv$ID$ = vec3($RESX$*2, $RESY$*2, $RESZ$*2)\n";
const std::string fluid_with_obstacle =
"\n\
using_obstacle_s$ID$ = True\n";
const std::string fluid_with_guiding =
"\n\
using_guiding_s$ID$ = True\n";
const std::string fluid_with_fractions =
"\n\
using_fractions_s$ID$ = True\n";
const std::string fluid_with_invel =
"\n\
using_invel_s$ID$ = True\n";
const std::string fluid_with_outflow =
"\n\
using_outflow_s$ID$ = True\n";
const std::string fluid_with_sndparts =
"\n\
using_sndparts_s$ID$ = True\n";
//////////////////////////////////////////////////////////////////////
// ADAPTIVE TIME STEPPING
//////////////////////////////////////////////////////////////////////
const std::string fluid_time_stepping =
"\n\
mantaMsg('Fluid adaptive time stepping')\n\
s$ID$.frameLength = frameLength_s$ID$\n\
s$ID$.timestepMin = s$ID$.frameLength / max(1, timestepsMax_s$ID$)\n\
s$ID$.timestepMax = s$ID$.frameLength / max(1, timestepsMin_s$ID$)\n\
s$ID$.cfl = cflCond_s$ID$\n\
s$ID$.timePerFrame = timePerFrame_s$ID$\n\
s$ID$.timestep = dt0_s$ID$\n\
s$ID$.timeTotal = timeTotal_s$ID$\n\
#mantaMsg('timestep: ' + str(s$ID$.timestep) + ' // timPerFrame: ' + str(s$ID$.timePerFrame) + ' // frameLength: ' + str(s$ID$.frameLength) + ' // timeTotal: ' + str(s$ID$.timeTotal) )\n";
const std::string fluid_adapt_time_step =
"\n\
def fluid_adapt_time_step_$ID$():\n\
mantaMsg('Fluid adapt time step')\n\
\n\
# time params are animatable\n\
s$ID$.frameLength = frameLength_s$ID$\n\
s$ID$.cfl = cflCond_s$ID$\n\
s$ID$.timestepMin = s$ID$.frameLength / max(1, timestepsMax_s$ID$)\n\
s$ID$.timestepMax = s$ID$.frameLength / max(1, timestepsMin_s$ID$)\n\
\n\
# ensure that vel grid is full (remember: adaptive domain can reallocate solver)\n\
copyRealToVec3(sourceX=x_vel_s$ID$, sourceY=y_vel_s$ID$, sourceZ=z_vel_s$ID$, target=vel_s$ID$)\n\
maxVel_s$ID$ = vel_s$ID$.getMax() if vel_s$ID$ else 0\n\
if using_adaptTime_s$ID$:\n\
mantaMsg('Adapt timestep, maxvel: ' + str(maxVel_s$ID$))\n\
s$ID$.adaptTimestep(maxVel_s$ID$)\n";
//////////////////////////////////////////////////////////////////////
// GRIDS
//////////////////////////////////////////////////////////////////////
const std::string fluid_alloc =
"\n\
mantaMsg('Fluid alloc data')\n\
flags_s$ID$ = s$ID$.create(FlagGrid, name='$NAME_FLAGS$')\n\
vel_s$ID$ = s$ID$.create(MACGrid, name='$NAME_VELOCITY$', sparse=True)\n\
velTmp_s$ID$ = s$ID$.create(MACGrid, name='$NAME_VELOCITYTMP$', sparse=True)\n\
x_vel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_VELOCITY_X$')\n\
y_vel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_VELOCITY_Y$')\n\
z_vel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_VELOCITY_Z$')\n\
pressure_s$ID$ = s$ID$.create(RealGrid, name='$NAME_PRESSURE$')\n\
phiObs_s$ID$ = s$ID$.create(LevelsetGrid, name='$NAME_PHIOBS$')\n\
phiSIn_s$ID$ = s$ID$.create(LevelsetGrid, name='$NAME_PHISIN$') # helper for static flow objects\n\
phiIn_s$ID$ = s$ID$.create(LevelsetGrid, name='$NAME_PHIIN$')\n\
phiOut_s$ID$ = s$ID$.create(LevelsetGrid, name='$NAME_PHIOUT$')\n\
forces_s$ID$ = s$ID$.create(Vec3Grid, name='$NAME_FORCES$')\n\
x_force_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FORCES_X$')\n\
y_force_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FORCES_Y$')\n\
z_force_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FORCES_Z$')\n\
obvel_s$ID$ = None\n\
\n\
# Set some initial values\n\
phiObs_s$ID$.setConst(9999)\n\
phiSIn_s$ID$.setConst(9999)\n\
phiIn_s$ID$.setConst(9999)\n\
phiOut_s$ID$.setConst(9999)\n\
\n\
# Keep track of important objects in dict to load them later on\n\
fluid_data_dict_final_s$ID$ = { 'vel' : vel_s$ID$ }\n\
fluid_data_dict_resume_s$ID$ = { 'phiObs' : phiObs_s$ID$, 'phiIn' : phiIn_s$ID$, 'phiOut' : phiOut_s$ID$, 'flags' : flags_s$ID$, 'velTmp' : velTmp_s$ID$ }\n";
const std::string fluid_alloc_obstacle =
"\n\
mantaMsg('Allocating obstacle data')\n\
numObs_s$ID$ = s$ID$.create(RealGrid, name='$NAME_NUMOBS$')\n\
phiObsSIn_s$ID$ = s$ID$.create(LevelsetGrid, name='$NAME_PHIOBSSIN$') # helper for static obstacle objects\n\
phiObsIn_s$ID$ = s$ID$.create(LevelsetGrid, name='$NAME_PHIOBSIN$')\n\
obvel_s$ID$ = s$ID$.create(MACGrid, name='$NAME_OBVEL$')\n\
obvelC_s$ID$ = s$ID$.create(Vec3Grid, name='$NAME_OBVELC$')\n\
x_obvel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_OBVEL_X$')\n\
y_obvel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_OBVEL_Y$')\n\
z_obvel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_OBVEL_Z$')\n\
\n\
# Set some initial values\n\
phiObsSIn_s$ID$.setConst(9999)\n\
phiObsIn_s$ID$.setConst(9999)\n\
\n\
if 'fluid_data_dict_resume_s$ID$' in globals():\n\
fluid_data_dict_resume_s$ID$.update(phiObsIn=phiObsIn_s$ID$)\n";
const std::string fluid_alloc_guiding =
"\n\
mantaMsg('Allocating guiding data')\n\
velT_s$ID$ = s$ID$.create(MACGrid, name='$NAME_VELT$')\n\
weightGuide_s$ID$ = s$ID$.create(RealGrid, name='$NAME_WEIGHTGUIDE$')\n\
numGuides_s$ID$ = s$ID$.create(RealGrid, name='$NAME_NUMGUIDES$')\n\
phiGuideIn_s$ID$ = s$ID$.create(LevelsetGrid, name='$NAME_PHIGUIDEIN$')\n\
guidevelC_s$ID$ = s$ID$.create(Vec3Grid, name='$NAME_GUIDEVELC$')\n\
x_guidevel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_GUIDEVEL_X$')\n\
y_guidevel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_GUIDEVEL_Y$')\n\
z_guidevel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_GUIDEVEL_Z$')\n\
\n\
# Final guide vel grid needs to have independent size\n\
guidevel_sg$ID$ = sg$ID$.create(MACGrid, name='$NAME_VELOCITY_GUIDE$')\n\
\n\
# Keep track of important objects in dict to load them later on\n\
fluid_guiding_dict_s$ID$ = { 'guidevel' : guidevel_sg$ID$ }\n";
const std::string fluid_alloc_fractions =
"\n\
mantaMsg('Allocating fractions data')\n\
fractions_s$ID$ = s$ID$.create(MACGrid, name='$NAME_FRACTIONS$')\n";
const std::string fluid_alloc_invel =
"\n\
mantaMsg('Allocating initial velocity data')\n\
invelC_s$ID$ = s$ID$.create(VecGrid, name='$NAME_INVELC$')\n\
x_invel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_INVEL_X$')\n\
y_invel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_INVEL_Y$')\n\
z_invel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_INVEL_Z$')\n";
const std::string fluid_alloc_outflow =
"\n\
mantaMsg('Allocating outflow data')\n\
phiOutSIn_s$ID$ = s$ID$.create(LevelsetGrid, name='$NAME_PHIOUTSIN$') # helper for static outflow objects\n\
phiOutIn_s$ID$ = s$ID$.create(LevelsetGrid, name='$NAME_PHIOUTIN$')\n\
\n\
# Set some initial values\n\
phiOutSIn_s$ID$.setConst(9999)\n\
phiOutIn_s$ID$.setConst(9999)\n\
\n\
if 'fluid_data_dict_resume_s$ID$' in globals():\n\
fluid_data_dict_resume_s$ID$.update(phiOutIn=phiOutIn_s$ID$)\n";
//////////////////////////////////////////////////////////////////////
// PRE / POST STEP
//////////////////////////////////////////////////////////////////////
const std::string fluid_pre_step =
"\n\
def fluid_pre_step_$ID$():\n\
mantaMsg('Fluid pre step')\n\
\n\
phiObs_s$ID$.setConst(9999)\n\
phiOut_s$ID$.setConst(9999)\n\
\n\
# Main vel grid is copied in adapt time step function\n\
\n\
if using_obstacle_s$ID$:\n\
# Average out velocities from multiple obstacle objects at one cell\n\
x_obvel_s$ID$.safeDivide(numObs_s$ID$)\n\
y_obvel_s$ID$.safeDivide(numObs_s$ID$)\n\
z_obvel_s$ID$.safeDivide(numObs_s$ID$)\n\
copyRealToVec3(sourceX=x_obvel_s$ID$, sourceY=y_obvel_s$ID$, sourceZ=z_obvel_s$ID$, target=obvelC_s$ID$)\n\
\n\
if using_invel_s$ID$:\n\
copyRealToVec3(sourceX=x_invel_s$ID$, sourceY=y_invel_s$ID$, sourceZ=z_invel_s$ID$, target=invelC_s$ID$)\n\
\n\
if using_guiding_s$ID$:\n\
weightGuide_s$ID$.multConst(0)\n\
weightGuide_s$ID$.addConst(alpha_sg$ID$)\n\
interpolateMACGrid(source=guidevel_sg$ID$, target=velT_s$ID$)\n\
velT_s$ID$.multConst(vec3(gamma_sg$ID$))\n\
\n\
x_force_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
y_force_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
z_force_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
copyRealToVec3(sourceX=x_force_s$ID$, sourceY=y_force_s$ID$, sourceZ=z_force_s$ID$, target=forces_s$ID$)\n\
\n\
# If obstacle has velocity, i.e. is a moving obstacle, switch to dynamic preconditioner\n\
if using_smoke_s$ID$ and using_obstacle_s$ID$ and obvelC_s$ID$.getMax() > 0:\n\
mantaMsg('Using dynamic preconditioner')\n\
preconditioner_s$ID$ = PcMGDynamic\n\
else:\n\
mantaMsg('Using static preconditioner')\n\
preconditioner_s$ID$ = PcMGStatic\n";
const std::string fluid_post_step =
"\n\
def fluid_post_step_$ID$():\n\
mantaMsg('Fluid post step')\n\
\n\
# Copy vel grid to reals grids (which Blender internal will in turn use for vel access)\n\
copyVec3ToReal(source=vel_s$ID$, targetX=x_vel_s$ID$, targetY=y_vel_s$ID$, targetZ=z_vel_s$ID$)\n\
if using_guiding_s$ID$:\n\
copyVec3ToReal(source=guidevel_sg$ID$, targetX=x_guidevel_s$ID$, targetY=y_guidevel_s$ID$, targetZ=z_guidevel_s$ID$)\n";
//////////////////////////////////////////////////////////////////////
// DESTRUCTION
//////////////////////////////////////////////////////////////////////
const std::string fluid_delete_all =
"\n\
mantaMsg('Deleting fluid')\n\
# Clear all helper dictionaries first\n\
mantaMsg('Clear helper dictionaries')\n\
if 'liquid_data_dict_final_s$ID$' in globals(): liquid_data_dict_final_s$ID$.clear()\n\
if 'liquid_data_dict_resume_s$ID$' in globals(): liquid_data_dict_resume_s$ID$.clear()\n\
if 'liquid_mesh_dict_s$ID$' in globals(): liquid_mesh_dict_s$ID$.clear()\n\
if 'liquid_meshvel_dict_s$ID$' in globals(): liquid_meshvel_dict_s$ID$.clear()\n\
if 'liquid_particles_final_dict_s$ID$' in globals(): liquid_particles_final_dict_s$ID$.clear()\n\
if 'liquid_particles_resume_dict_s$ID$' in globals(): liquid_particles_resume_dict_s$ID$.clear()\n\
\n\
if 'smoke_data_dict_final_s$ID$' in globals(): smoke_data_dict_final_s$ID$.clear()\n\
if 'smoke_data_dict_resume_s$ID$' in globals(): smoke_data_dict_resume_s$ID$.clear()\n\
if 'smoke_noise_dict_final_s$ID$' in globals(): smoke_noise_dict_final_s$ID$.clear()\n\
if 'smoke_noise_dict_resume_s$ID$' in globals(): smoke_noise_dict_resume_s$ID$.clear()\n\
\n\
if 'fluid_data_dict_final_s$ID$' in globals(): fluid_data_dict_final_s$ID$.clear()\n\
if 'fluid_data_dict_resume_s$ID$' in globals(): fluid_data_dict_resume_s$ID$.clear()\n\
if 'fluid_guiding_dict_s$ID$' in globals(): fluid_guiding_dict_s$ID$.clear()\n\
if 'fluid_vel_dict_s$ID$' in globals(): fluid_vel_dict_s$ID$.clear()\n\
\n\
# Delete all children from objects (e.g. pdata for particles)\n\
mantaMsg('Release solver childrens children')\n\
for var in list(globals()):\n\
if var.endswith('_pp$ID$') or var.endswith('_mesh$ID$'):\n\
del globals()[var]\n\
\n\
# Now delete children from solver objects\n\
mantaMsg('Release solver children')\n\
for var in list(globals()):\n\
if var.endswith('_s$ID$') or var.endswith('_sn$ID$') or var.endswith('_sm$ID$') or var.endswith('_sp$ID$') or var.endswith('_sg$ID$'):\n\
del globals()[var]\n\
\n\
# Extra cleanup for multigrid and fluid guiding\n\
mantaMsg('Release multigrid')\n\
if 's$ID$' in globals(): releaseMG(s$ID$)\n\
if 'sn$ID$' in globals(): releaseMG(sn$ID$)\n\
mantaMsg('Release fluid guiding')\n\
releaseBlurPrecomp()\n\
\n\
# Release unreferenced memory (if there is some left, can in fact happen)\n\
gc.collect()\n\
\n\
# Now it is safe to delete solver objects (always need to be deleted last)\n\
mantaMsg('Delete base solver')\n\
if 's$ID$' in globals(): del s$ID$\n\
mantaMsg('Delete noise solver')\n\
if 'sn$ID$' in globals(): del sn$ID$\n\
mantaMsg('Delete mesh solver')\n\
if 'sm$ID$' in globals(): del sm$ID$\n\
mantaMsg('Delete particle solver')\n\
if 'sp$ID$' in globals(): del sp$ID$\n\
mantaMsg('Delete guiding solver')\n\
if 'sg$ID$' in globals(): del sg$ID$\n\
\n\
# Release unreferenced memory (if there is some left)\n\
gc.collect()\n";
//////////////////////////////////////////////////////////////////////
// BAKE
//////////////////////////////////////////////////////////////////////
/* This has to match the behavior of BLI_path_frame,
* for positive and negative frame numbers. */
const std::string fluid_cache_helper =
"\n\
def fluid_cache_get_framenr_formatted_$ID$(framenr):\n\
return str(framenr).zfill(4) if framenr >= 0 else str(framenr).zfill(5)\n";
const std::string fluid_bake_multiprocessing =
"\n\
def fluid_cache_multiprocessing_start_$ID$(function, framenr, file_name=None, format_data=None, format_noise=None, format_mesh=None, format_particles=None, format_guiding=None, path_data=None, path_noise=None, path_mesh=None, path_particles=None, path_guiding=None, dict=None, do_join=True, resumable=False):\n\
mantaMsg('Multiprocessing cache')\n\
if __name__ == '__main__':\n\
args = (framenr,)\n\
if file_name:\n\
args += (file_name,)\n\
if format_data:\n\
args += (format_data,)\n\
if format_noise:\n\
args += (format_noise,)\n\
if format_mesh:\n\
args += (format_mesh,)\n\
if format_particles:\n\
args += (format_particles,)\n\
if format_guiding:\n\
args += (format_guiding,)\n\
if path_data:\n\
args += (path_data,)\n\
if path_noise:\n\
args += (path_noise,)\n\
if path_mesh:\n\
args += (path_mesh,)\n\
if path_particles:\n\
args += (path_particles,)\n\
if path_guiding:\n\
args += (path_guiding,)\n\
if dict:\n\
args += (dict,)\n\
args += (resumable,)\n\
p$ID$ = multiprocessing.Process(target=function, args=args)\n\
p$ID$.start()\n\
if do_join:\n\
p$ID$.join()\n";
const std::string fluid_bake_data =
"\n\
def bake_fluid_process_data_$ID$(framenr, format_data, path_data):\n\
mantaMsg('Bake fluid data')\n\
\n\
s$ID$.frame = framenr\n\
s$ID$.frameLength = frameLength_s$ID$\n\
s$ID$.timeTotal = timeTotal_s$ID$\n\
\n\
start_time = time.time()\n\
if using_smoke_s$ID$:\n\
smoke_adaptive_step_$ID$(framenr)\n\
if using_liquid_s$ID$:\n\
liquid_adaptive_step_$ID$(framenr)\n\
mantaMsg('--- Step: %s seconds ---' % (time.time() - start_time))\n\
\n\
def bake_fluid_data_$ID$(path_data, framenr, format_data):\n\
if not withMPBake or isWindows:\n\
bake_fluid_process_data_$ID$(framenr, format_data, path_data)\n\
else:\n\
fluid_cache_multiprocessing_start_$ID$(function=bake_fluid_process_data_$ID$, framenr=framenr, format_data=format_data, path_data=path_data, do_join=False)\n";
const std::string fluid_bake_noise =
"\n\
def bake_noise_process_$ID$(framenr, format_noise, path_noise):\n\
mantaMsg('Bake fluid noise')\n\
\n\
sn$ID$.frame = framenr\n\
sn$ID$.frameLength = frameLength_s$ID$\n\
sn$ID$.timeTotal = timeTotal_s$ID$\n\
sn$ID$.timestep = frameLength_s$ID$ # no adaptive timestep for noise\n\
\n\
smoke_step_noise_$ID$(framenr)\n\
\n\
def bake_noise_$ID$(path_noise, framenr, format_noise):\n\
if not withMPBake or isWindows:\n\
bake_noise_process_$ID$(framenr, format_noise, path_noise)\n\
else:\n\
fluid_cache_multiprocessing_start_$ID$(function=bake_noise_process_$ID$, framenr=framenr, format_noise=format_noise, path_noise=path_noise)\n";
const std::string fluid_bake_mesh =
"\n\
def bake_mesh_process_$ID$(framenr, format_data, format_mesh, path_mesh):\n\
mantaMsg('Bake fluid mesh')\n\
\n\
sm$ID$.frame = framenr\n\
sm$ID$.frameLength = frameLength_s$ID$\n\
sm$ID$.timeTotal = timeTotal_s$ID$\n\
sm$ID$.timestep = frameLength_s$ID$ # no adaptive timestep for mesh\n\
\n\
#if using_smoke_s$ID$:\n\
# TODO(sebbas): Future update could include smoke mesh (vortex sheets)\n\
if using_liquid_s$ID$:\n\
liquid_step_mesh_$ID$()\n\
liquid_save_mesh_$ID$(path_mesh, framenr, format_mesh)\n\
if using_speedvectors_s$ID$:\n\
liquid_save_meshvel_$ID$(path_mesh, framenr, format_data)\n\
\n\
def bake_mesh_$ID$(path_mesh, framenr, format_data, format_mesh):\n\
if not withMPBake or isWindows:\n\
bake_mesh_process_$ID$(framenr, format_data, format_mesh, path_mesh)\n\
else:\n\
fluid_cache_multiprocessing_start_$ID$(function=bake_mesh_process_$ID$, framenr=framenr, format_data=format_data, format_mesh=format_mesh, path_mesh=path_mesh)\n";
const std::string fluid_bake_particles =
"\n\
def bake_particles_process_$ID$(framenr, format_particles, path_particles, resumable):\n\
mantaMsg('Bake secondary particles')\n\
\n\
sp$ID$.frame = framenr\n\
sp$ID$.frameLength = frameLength_s$ID$\n\
sp$ID$.timeTotal = timeTotal_s$ID$\n\
sp$ID$.timestep = frameLength_s$ID$ # no adaptive timestep for particles\n\
\n\
#if using_smoke_s$ID$:\n\
# TODO(sebbas): Future update could include smoke particles (e.g. fire sparks)\n\
if using_liquid_s$ID$:\n\
liquid_step_particles_$ID$()\n\
liquid_save_particles_$ID$(path_particles, framenr, format_particles, resumable)\n\
\n\
def bake_particles_$ID$(path_particles, framenr, format_particles, resumable):\n\
if not withMPBake or isWindows:\n\
bake_particles_process_$ID$(framenr, format_particles, path_particles, resumable)\n\
else:\n\
fluid_cache_multiprocessing_start_$ID$(function=bake_particles_process_$ID$, framenr=framenr, format_particles=format_particles, path_particles=path_particles, resumable=resumable)\n";
const std::string fluid_bake_guiding =
"\n\
def bake_guiding_process_$ID$(framenr, format_guiding, path_guiding, resumable):\n\
mantaMsg('Bake fluid guiding')\n\
\n\
# Average out velocities from multiple guiding objects at one cell\n\
x_guidevel_s$ID$.safeDivide(numGuides_s$ID$)\n\
y_guidevel_s$ID$.safeDivide(numGuides_s$ID$)\n\
z_guidevel_s$ID$.safeDivide(numGuides_s$ID$)\n\
copyRealToVec3(sourceX=x_guidevel_s$ID$, sourceY=y_guidevel_s$ID$, sourceZ=z_guidevel_s$ID$, target=guidevelC_s$ID$)\n\
\n\
mantaMsg('Extrapolating guiding velocity')\n\
# ensure velocities inside of guiding object, slightly add guiding vels outside of object too\n\
extrapolateVec3Simple(vel=guidevelC_s$ID$, phi=phiGuideIn_s$ID$, distance=6, inside=True)\n\
extrapolateVec3Simple(vel=guidevelC_s$ID$, phi=phiGuideIn_s$ID$, distance=3, inside=False)\n\
resampleVec3ToMac(source=guidevelC_s$ID$, target=guidevel_sg$ID$)\n\
\n\
fluid_save_guiding_$ID$(path_guiding, framenr, format_guiding, resumable)\n\
\n\
def bake_guiding_$ID$(path_guiding, framenr, format_guiding, resumable):\n\
if not withMPBake or isWindows:\n\
bake_guiding_process_$ID$(framenr, format_guiding, path_guiding, resumable)\n\
else:\n\
fluid_cache_multiprocessing_start_$ID$(function=bake_guiding_process_$ID$, framenr=framenr, format_guiding=format_guiding, path_guiding=path_guiding, resumable=resumable)\n";
//////////////////////////////////////////////////////////////////////
// IMPORT
//////////////////////////////////////////////////////////////////////
const std::string fluid_file_import =
"\n\
def fluid_file_import_s$ID$(dict, path, framenr, file_format, file_name=None):\n\
mantaMsg('Fluid file import, frame: ' + str(framenr))\n\
try:\n\
framenr = fluid_cache_get_framenr_formatted_$ID$(framenr)\n\
# New cache: Try to load the data from a single file\n\
loadCombined = 0\n\
if file_name is not None:\n\
file = os.path.join(path, file_name + '_' + framenr + file_format)\n\
if os.path.isfile(file):\n\
if file_format == '.vdb':\n\
loadCombined = load(name=file, objects=list(dict.values()), worldSize=domainSize_s$ID$)\n\
elif file_format == '.bobj.gz' or file_format == '.obj':\n\
for name, object in dict.items():\n\
if os.path.isfile(file):\n\
loadCombined = object.load(file)\n\
\n\
# Old cache: Try to load the data from separate files, i.e. per object with the object based load() function\n\
if not loadCombined:\n\
for name, object in dict.items():\n\
file = os.path.join(path, name + '_' + framenr + file_format)\n\
if os.path.isfile(file):\n\
loadCombined = object.load(file)\n\
\n\
if not loadCombined:\n\
mantaMsg('Could not load file ' + str(file))\n\
\n\
except Exception as e:\n\
mantaMsg('Exception in Python fluid file import: ' + str(e))\n\
pass # Just skip file load errors for now\n";
const std::string fluid_load_guiding =
"\n\
def fluid_load_guiding_$ID$(path, framenr, file_format):\n\
mantaMsg('Fluid load guiding, frame ' + str(framenr))\n\
guidevel_sg$ID$.setName('$NAME_VELOCITY_GUIDE$')\n\
fluid_file_import_s$ID$(dict=fluid_guiding_dict_s$ID$, path=path, framenr=framenr, file_format=file_format, file_name=file_guiding_s$ID$)\n\
\n\
copyVec3ToReal(source=guidevel_sg$ID$, targetX=x_guidevel_s$ID$, targetY=y_guidevel_s$ID$, targetZ=z_guidevel_s$ID$)\n";
const std::string fluid_load_vel =
"\n\
def fluid_load_vel_$ID$(path, framenr, file_format):\n\
mantaMsg('Fluid load vel, frame ' + str(framenr))\n\
guidevel_sg$ID$.setName('$NAME_VELOCITY$') # for loading data the guidevel grid will pretend to be the vel grid\n\
fluid_vel_dict_s$ID$ = { 'vel' : guidevel_sg$ID$ }\n\
fluid_file_import_s$ID$(dict=fluid_vel_dict_s$ID$, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$)\n";
//////////////////////////////////////////////////////////////////////
// EXPORT
//////////////////////////////////////////////////////////////////////
const std::string fluid_file_export =
"\n\
def fluid_file_export_s$ID$(framenr, file_format, path, dict, file_name=None, mode_override=True, skip_subframes=True, clipGrid=None):\n\
if skip_subframes and ((timePerFrame_s$ID$ + dt0_s$ID$) < frameLength_s$ID$):\n\
return\n\
mantaMsg('Fluid file export, frame: ' + str(framenr))\n\
try:\n\
framenr = fluid_cache_get_framenr_formatted_$ID$(framenr)\n\
if not os.path.exists(path):\n\
os.makedirs(path)\n\
\n\
# New cache: Try to save the data to a single file\n\
saveCombined = 0\n\
if file_name is not None:\n\
file = os.path.join(path, file_name + '_' + framenr + file_format)\n\
if not os.path.isfile(file) or mode_override:\n\
if file_format == '.vdb':\n\
saveCombined = save(name=file, objects=list(dict.values()), worldSize=domainSize_s$ID$, skipDeletedParts=True, compression=vdbCompression_s$ID$, precision=vdbPrecision_s$ID$, clip=vdbClip_s$ID$, clipGrid=clipGrid, meta=True)\n\
elif file_format == '.bobj.gz' or file_format == '.obj':\n\
for name, object in dict.items():\n\
if not os.path.isfile(file) or mode_override:\n\
saveCombined = object.save(file)\n\
\n\
# Old cache: Try to save the data to separate files, i.e. per object with the object based save() function\n\
if not saveCombined:\n\
for name, object in dict.items():\n\
file = os.path.join(path, name + '_' + framenr + file_format)\n\
if not os.path.isfile(file) or mode_override: object.save(file)\n\
\n\
except Exception as e:\n\
mantaMsg('Exception in Python fluid file export: ' + str(e))\n\
pass # Just skip file save errors for now\n";
const std::string fluid_save_guiding =
"\n\
def fluid_save_guiding_$ID$(path, framenr, file_format, resumable):\n\
mantaMsg('Fluid save guiding, frame ' + str(framenr))\n\
dict = fluid_guiding_dict_s$ID$\n\
if not withMPSave or isWindows:\n\
fluid_file_export_s$ID$(dict=dict, framenr=framenr, file_format=file_format, path=path, file_name=file_guiding_s$ID$)\n\
else:\n\
fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_guiding_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n";
//////////////////////////////////////////////////////////////////////
// STANDALONE MODE
//////////////////////////////////////////////////////////////////////
const std::string fluid_standalone =
"\n\
gui = None\n\
if (GUI):\n\
gui=Gui()\n\
gui.show()\n\
gui.pause()\n\
\n\
cache_resumable = $CACHE_RESUMABLE$\n\
cache_dir = '$CACHE_DIR$'\n\
file_format_data = '$CACHE_DATA_FORMAT$'\n\
file_format_mesh = '$CACHE_MESH_FORMAT$'\n\
\n\
# How many frame to load from cache\n\
from_cache_count = 100\n\
\n\
loop_count = 0\n\
while current_frame_s$ID$ <= end_frame_s$ID$:\n\
\n\
# Load already simulated data from cache:\n\
if loop_count < from_cache_count:\n\
load_data(current_frame_s$ID$, cache_resumable)\n\
\n\
# Otherwise simulate new data\n\
else:\n\
while(s$ID$.frame <= current_frame_s$ID$):\n\
if using_adaptTime_s$ID$:\n\
fluid_adapt_time_step_$ID$()\n\
step(current_frame_s$ID$)\n\
\n\
current_frame_s$ID$ += 1\n\
loop_count += 1\n\
\n\
if gui:\n\
gui.pause()\n";
//////////////////////////////////////////////////////////////////////
// SCRIPT SECTION HEADERS
//////////////////////////////////////////////////////////////////////
const std::string header_libraries =
"\n\
######################################################################\n\
## LIBRARIES\n\
######################################################################\n";
const std::string header_main =
"\n\
######################################################################\n\
## MAIN\n\
######################################################################\n";
const std::string header_prepost =
"\n\
######################################################################\n\
## PRE/POST STEPS\n\
######################################################################\n";
const std::string header_steps =
"\n\
######################################################################\n\
## STEPS\n\
######################################################################\n";
const std::string header_import =
"\n\
######################################################################\n\
## IMPORT\n\
######################################################################\n";
const std::string header_grids =
"\n\
######################################################################\n\
## GRIDS\n\
######################################################################\n";
const std::string header_solvers =
"\n\
######################################################################\n\
## SOLVERS\n\
######################################################################\n";
const std::string header_variables =
"\n\
######################################################################\n\
## VARIABLES\n\
######################################################################\n";
const std::string header_time =
"\n\
######################################################################\n\
## ADAPTIVE TIME\n\
######################################################################\n";
const std::string header_gridinit =
"\n\
######################################################################\n\
## DOMAIN INIT\n\
######################################################################\n";

View File

@@ -0,0 +1,514 @@
/* SPDX-FileCopyrightText: 2016 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_mantaflow
*/
#include <string>
//////////////////////////////////////////////////////////////////////
// VARIABLES
//////////////////////////////////////////////////////////////////////
const std::string liquid_variables =
"\n\
mantaMsg('Liquid variables')\n\
narrowBandWidth_s$ID$ = 3\n\
combineBandWidth_s$ID$ = narrowBandWidth_s$ID$ - 1\n\
adjustedNarrowBandWidth_s$ID$ = $PARTICLE_BAND_WIDTH$ # only used in adjustNumber to control band width\n\
particleNumber_s$ID$ = $PARTICLE_NUMBER$\n\
minParticles_s$ID$ = $PARTICLE_MINIMUM$\n\
maxParticles_s$ID$ = $PARTICLE_MAXIMUM$\n\
radiusFactor_s$ID$ = $PARTICLE_RADIUS$\n\
using_mesh_s$ID$ = $USING_MESH$\n\
using_final_mesh_s$ID$ = $USING_IMPROVED_MESH$\n\
using_fractions_s$ID$ = $USING_FRACTIONS$\n\
using_apic_s$ID$ = $USING_APIC$\n\
using_viscosity_s$ID$ = $USING_VISCOSITY$\n\
fracThreshold_s$ID$ = $FRACTIONS_THRESHOLD$\n\
fracDistance_s$ID$ = $FRACTIONS_DISTANCE$\n\
flipRatio_s$ID$ = $FLIP_RATIO$\n\
concaveUpper_s$ID$ = $MESH_CONCAVE_UPPER$\n\
concaveLower_s$ID$ = $MESH_CONCAVE_LOWER$\n\
meshRadiusFactor_s$ID$ = $MESH_PARTICLE_RADIUS$\n\
smoothenPos_s$ID$ = $MESH_SMOOTHEN_POS$\n\
smoothenNeg_s$ID$ = $MESH_SMOOTHEN_NEG$\n\
randomness_s$ID$ = $PARTICLE_RANDOMNESS$\n\
surfaceTension_s$ID$ = $LIQUID_SURFACE_TENSION$\n\
maxSysParticles_s$ID$ = $PP_PARTICLE_MAXIMUM$\n\
viscosityValue_s$ID$ = $VISCOSITY_VALUE$\n";
const std::string liquid_variables_particles =
"\n\
tauMin_wc_sp$ID$ = $SNDPARTICLE_TAU_MIN_WC$\n\
tauMax_wc_sp$ID$ = $SNDPARTICLE_TAU_MAX_WC$\n\
tauMin_ta_sp$ID$ = $SNDPARTICLE_TAU_MIN_TA$\n\
tauMax_ta_sp$ID$ = $SNDPARTICLE_TAU_MAX_TA$\n\
tauMin_k_sp$ID$ = $SNDPARTICLE_TAU_MIN_K$\n\
tauMax_k_sp$ID$ = $SNDPARTICLE_TAU_MAX_K$\n\
k_wc_sp$ID$ = $SNDPARTICLE_K_WC$\n\
k_ta_sp$ID$ = $SNDPARTICLE_K_TA$\n\
k_b_sp$ID$ = $SNDPARTICLE_K_B$\n\
k_d_sp$ID$ = $SNDPARTICLE_K_D$\n\
lMin_sp$ID$ = $SNDPARTICLE_L_MIN$\n\
lMax_sp$ID$ = $SNDPARTICLE_L_MAX$\n\
c_s_sp$ID$ = 0.4 # classification constant for snd parts\n\
c_b_sp$ID$ = 0.77 # classification constant for snd parts\n\
pot_radius_sp$ID$ = $SNDPARTICLE_POTENTIAL_RADIUS$\n\
update_radius_sp$ID$ = $SNDPARTICLE_UPDATE_RADIUS$\n\
using_snd_pushout_sp$ID$ = $SNDPARTICLE_BOUNDARY_PUSHOUT$\n";
//////////////////////////////////////////////////////////////////////
// GRIDS & MESH & PARTICLESYSTEM
//////////////////////////////////////////////////////////////////////
const std::string liquid_alloc =
"\n\
mantaMsg('Liquid alloc')\n\
phiParts_s$ID$ = s$ID$.create(LevelsetGrid, name='$NAME_PHIPARTS$')\n\
phi_s$ID$ = s$ID$.create(LevelsetGrid, name='$NAME_PHI$')\n\
phiTmp_s$ID$ = s$ID$.create(LevelsetGrid, name='$NAME_PHITMP$')\n\
velOld_s$ID$ = s$ID$.create(MACGrid, name='$NAME_VELOLD$')\n\
velParts_s$ID$ = s$ID$.create(MACGrid, name='$NAME_VELPARTS$')\n\
mapWeights_s$ID$ = s$ID$.create(MACGrid, name='$NAME_MAPWEIGHTS$')\n\
fractions_s$ID$ = None # allocated dynamically\n\
curvature_s$ID$ = None\n\
\n\
pp_s$ID$ = s$ID$.create(BasicParticleSystem, name='$NAME_PARTS$')\n\
pVel_pp$ID$ = pp_s$ID$.create(PdataVec3, name='$NAME_PARTSVELOCITY$')\n\
\n\
pCx_pp$ID$ = None\n\
pCy_pp$ID$ = None\n\
pCz_pp$ID$ = None\n\
if using_apic_s$ID$:\n\
pCx_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\
pCy_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\
pCz_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\
\n\
# Acceleration data for particle nbs\n\
pindex_s$ID$ = s$ID$.create(ParticleIndexSystem, name='$NAME_PINDEX$')\n\
gpi_s$ID$ = s$ID$.create(IntGrid, name='$NAME_GPI$')\n\
\n\
# Keep track of important objects in dict to load them later on\n\
liquid_data_dict_final_s$ID$ = { 'pVel' : pVel_pp$ID$, 'pp' : pp_s$ID$ }\n\
liquid_data_dict_resume_s$ID$ = { 'phiParts' : phiParts_s$ID$, 'phi' : phi_s$ID$, 'phiTmp' : phiTmp_s$ID$ }\n";
const std::string liquid_alloc_mesh =
"\n\
mantaMsg('Liquid alloc mesh')\n\
phiParts_sm$ID$ = sm$ID$.create(LevelsetGrid, name='$NAME_PHIPARTS_MESH$')\n\
phi_sm$ID$ = sm$ID$.create(LevelsetGrid, name='$NAME_PHI_MESH$')\n\
pp_sm$ID$ = sm$ID$.create(BasicParticleSystem, name='$NAME_PP_MESH$')\n\
flags_sm$ID$ = sm$ID$.create(FlagGrid, name='$NAME_FLAGS_MESH$')\n\
mesh_sm$ID$ = sm$ID$.create(Mesh, name='$NAME_MESH$')\n\
\n\
if using_speedvectors_s$ID$:\n\
mVel_mesh$ID$ = mesh_sm$ID$.create(MdataVec3, name='$NAME_VELOCITYVEC_MESH$')\n\
vel_sm$ID$ = sm$ID$.create(MACGrid, name='$NAME_VELOCITY_MESH$')\n\
\n\
# Acceleration data for particle nbs\n\
pindex_sm$ID$ = sm$ID$.create(ParticleIndexSystem, name='$NAME_PINDEX_MESH$')\n\
gpi_sm$ID$ = sm$ID$.create(IntGrid, name='$NAME_GPI_MESH$')\n\
\n\
# Set some initial values\n\
phiParts_sm$ID$.setConst(9999)\n\
phi_sm$ID$.setConst(9999)\n\
\n\
# Keep track of important objects in dict to load them later on\n\
liquid_mesh_dict_s$ID$ = { 'lMesh' : mesh_sm$ID$ }\n\
\n\
if using_speedvectors_s$ID$:\n\
liquid_meshvel_dict_s$ID$ = { 'lVelMesh' : mVel_mesh$ID$ }\n";
const std::string liquid_alloc_viscosity =
"\n\
# Viscosity grids\n\
volumes_s$ID$ = sv$ID$.create(RealGrid)\n\
viscosity_s$ID$ = s$ID$.create(RealGrid)\n\
viscosity_s$ID$.setConst(viscosityValue_s$ID$)\n";
const std::string liquid_alloc_curvature =
"\n\
mantaMsg('Liquid alloc curvature')\n\
curvature_s$ID$ = s$ID$.create(RealGrid, name='$NAME_CURVATURE$')\n";
const std::string liquid_alloc_particles =
"\n\
ppSnd_sp$ID$ = sp$ID$.create(BasicParticleSystem, name='$NAME_PARTS_PARTICLES$')\n\
pVelSnd_pp$ID$ = ppSnd_sp$ID$.create(PdataVec3, name='$NAME_PARTSVEL_PARTICLES$')\n\
pForceSnd_pp$ID$ = ppSnd_sp$ID$.create(PdataVec3, name='$NAME_PARTSFORCE_PARTICLES$')\n\
pLifeSnd_pp$ID$ = ppSnd_sp$ID$.create(PdataReal, name='$NAME_PARTSLIFE_PARTICLES$')\n\
vel_sp$ID$ = sp$ID$.create(MACGrid, name='$NAME_VELOCITY_PARTICLES$')\n\
flags_sp$ID$ = sp$ID$.create(FlagGrid, name='$NAME_FLAGS_PARTICLES$')\n\
phi_sp$ID$ = sp$ID$.create(LevelsetGrid, name='$NAME_PHI_PARTICLES$')\n\
phiObs_sp$ID$ = sp$ID$.create(LevelsetGrid, name='$NAME_PHIOBS_PARTICLES$')\n\
phiOut_sp$ID$ = sp$ID$.create(LevelsetGrid, name='$NAME_PHIOUT_PARTICLES$')\n\
normal_sp$ID$ = sp$ID$.create(VecGrid, name='$NAME_NORMAL_PARTICLES$')\n\
neighborRatio_sp$ID$ = sp$ID$.create(RealGrid, name='$NAME_NEIGHBORRATIO_PARTICLES$')\n\
trappedAir_sp$ID$ = sp$ID$.create(RealGrid, name='$NAME_TRAPPEDAIR_PARTICLES$')\n\
waveCrest_sp$ID$ = sp$ID$.create(RealGrid, name='$NAME_WAVECREST_PARTICLES$')\n\
kineticEnergy_sp$ID$ = sp$ID$.create(RealGrid, name='$NAME_KINETICENERGY_PARTICLES$')\n\
\n\
# Set some initial values\n\
phi_sp$ID$.setConst(9999)\n\
phiObs_sp$ID$.setConst(9999)\n\
phiOut_sp$ID$.setConst(9999)\n\
\n\
# Keep track of important objects in dict to load them later on\n\
liquid_particles_dict_final_s$ID$ = { 'pVelSnd' : pVelSnd_pp$ID$, 'pLifeSnd' : pLifeSnd_pp$ID$, 'ppSnd' : ppSnd_sp$ID$ }\n\
liquid_particles_dict_resume_s$ID$ = { 'trappedAir' : trappedAir_sp$ID$, 'waveCrest' : waveCrest_sp$ID$, 'kineticEnergy' : kineticEnergy_sp$ID$ }\n";
const std::string liquid_init_phi =
"\n\
# Prepare domain\n\
phi_s$ID$.initFromFlags(flags_s$ID$)\n\
phiIn_s$ID$.initFromFlags(flags_s$ID$)\n";
//////////////////////////////////////////////////////////////////////
// STEP FUNCTIONS
//////////////////////////////////////////////////////////////////////
const std::string liquid_adaptive_step =
"\n\
def liquid_adaptive_step_$ID$(framenr):\n\
mantaMsg('Manta step, frame ' + str(framenr))\n\
s$ID$.frame = framenr\n\
\n\
fluid_pre_step_$ID$()\n\
\n\
flags_s$ID$.initDomain(boundaryWidth=1 if using_fractions_s$ID$ else 0, phiWalls=phiObs_s$ID$, outflow=boundConditions_s$ID$)\n\
\n\
if using_obstacle_s$ID$:\n\
mantaMsg('Extrapolating object velocity')\n\
# ensure velocities inside of obs object, slightly add obvels outside of obs object\n\
# extrapolate with phiObsIn before joining (static) phiObsSIn grid to prevent flows into static obs\n\
extrapolateVec3Simple(vel=obvelC_s$ID$, phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
extrapolateVec3Simple(vel=obvelC_s$ID$, phi=phiObsIn_s$ID$, distance=3, inside=False)\n\
resampleVec3ToMac(source=obvelC_s$ID$, target=obvel_s$ID$)\n\
\n\
mantaMsg('Initializing obstacle levelset')\n\
phiObsIn_s$ID$.join(phiObsSIn_s$ID$) # Join static obstacle map\n\
phiObsIn_s$ID$.floodFill(boundaryWidth=1)\n\
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=3, inside=False)\n\
phiObs_s$ID$.join(phiObsIn_s$ID$)\n\
\n\
# Additional sanity check: fill holes in phiObs which can result after joining with phiObsIn\n\
phiObs_s$ID$.floodFill(boundaryWidth=2 if using_fractions_s$ID$ else 1)\n\
extrapolateLsSimple(phi=phiObs_s$ID$, distance=6, inside=True)\n\
extrapolateLsSimple(phi=phiObs_s$ID$, distance=3)\n\
\n\
mantaMsg('Initializing fluid levelset')\n\
phiIn_s$ID$.join(phiSIn_s$ID$) # Join static flow map\n\
extrapolateLsSimple(phi=phiIn_s$ID$, distance=6, inside=True)\n\
extrapolateLsSimple(phi=phiIn_s$ID$, distance=3)\n\
phi_s$ID$.join(phiIn_s$ID$)\n\
\n\
if using_outflow_s$ID$:\n\
phiOutIn_s$ID$.join(phiOutSIn_s$ID$) # Join static outflow map\n\
phiOut_s$ID$.join(phiOutIn_s$ID$)\n\
\n\
if using_fractions_s$ID$:\n\
updateFractions(flags=flags_s$ID$, phiObs=phiObs_s$ID$, fractions=fractions_s$ID$, boundaryWidth=boundaryWidth_s$ID$, fracThreshold=fracThreshold_s$ID$)\n\
setObstacleFlags(flags=flags_s$ID$, phiObs=phiObs_s$ID$, phiOut=phiOut_s$ID$, fractions=fractions_s$ID$, phiIn=phiIn_s$ID$)\n\
\n\
if using_obstacle_s$ID$:\n\
# TODO(sebbas): Enable flags check again, currently produces unstable particle behavior\n\
phi_s$ID$.subtract(o=phiObsIn_s$ID$) #, flags=flags_s$ID$, subtractType=FlagObstacle)\n\
\n\
# add initial velocity: set invel as source grid to ensure const vels in inflow region, sampling makes use of this\n\
if using_invel_s$ID$:\n\
extrapolateVec3Simple(vel=invelC_s$ID$, phi=phiIn_s$ID$, distance=6, inside=True)\n\
# Using cell centered invels, a false isMAC flag ensures correct interpolation\n\
pVel_pp$ID$.setSource(grid=invelC_s$ID$, isMAC=False)\n\
# reset pvel grid source before sampling new particles - ensures that new particles are initialized with 0 velocity\n\
else:\n\
pVel_pp$ID$.setSource(grid=None, isMAC=False)\n\
\n\
pp_s$ID$.maxParticles = maxSysParticles_s$ID$ # remember, 0 means no particle cap\n\
sampleLevelsetWithParticles(phi=phiIn_s$ID$, flags=flags_s$ID$, parts=pp_s$ID$, discretization=particleNumber_s$ID$, randomness=randomness_s$ID$)\n\
flags_s$ID$.updateFromLevelset(phi_s$ID$)\n\
\n\
mantaMsg('Liquid step / s$ID$.frame: ' + str(s$ID$.frame))\n\
liquid_step_$ID$()\n\
\n\
s$ID$.step()\n\
\n\
fluid_post_step_$ID$()\n";
const std::string liquid_step =
"\n\
def liquid_step_$ID$():\n\
mantaMsg('Liquid step')\n\
\n\
mantaMsg('Advecting particles')\n\
pp_s$ID$.advectInGrid(flags=flags_s$ID$, vel=vel_s$ID$, integrationMode=IntRK4, deleteInObstacle=deleteInObstacle_s$ID$, stopInObstacle=False, skipNew=True)\n\
\n\
mantaMsg('Pushing particles out of obstacles')\n\
if using_obstacle_s$ID$ and using_fractions_s$ID$ and fracDistance_s$ID$ > 0:\n\
# Optional: Increase distance between fluid and obstacles (only obstacles, not borders)\n\
pushOutofObs(parts=pp_s$ID$, flags=flags_s$ID$, phiObs=phiObsIn_s$ID$, thresh=fracDistance_s$ID$)\n\
pushOutofObs(parts=pp_s$ID$, flags=flags_s$ID$, phiObs=phiObs_s$ID$)\n\
\n\
# save original states for later (used during mesh / secondary particle creation)\n\
# but only save the state at the beginning of an adaptive frame\n\
if not s$ID$.timePerFrame:\n\
phiTmp_s$ID$.copyFrom(phi_s$ID$)\n\
velTmp_s$ID$.copyFrom(vel_s$ID$)\n\
\n\
mantaMsg('Advecting phi')\n\
advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=phi_s$ID$, order=1) # first order is usually enough\n\
mantaMsg('Advecting velocity')\n\
advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=vel_s$ID$, order=2)\n\
\n\
# create level set of particles\n\
gridParticleIndex(parts=pp_s$ID$, flags=flags_s$ID$, indexSys=pindex_s$ID$, index=gpi_s$ID$)\n\
unionParticleLevelset(parts=pp_s$ID$, indexSys=pindex_s$ID$, flags=flags_s$ID$, index=gpi_s$ID$, phi=phiParts_s$ID$, radiusFactor=radiusFactor_s$ID$)\n\
\n\
# combine level set of particles with grid level set\n\
phi_s$ID$.addConst(1.) # shrink slightly\n\
phi_s$ID$.join(phiParts_s$ID$)\n\
extrapolateLsSimple(phi=phi_s$ID$, distance=narrowBandWidth_s$ID$+2, inside=True)\n\
extrapolateLsSimple(phi=phi_s$ID$, distance=3)\n\
phi_s$ID$.setBoundNeumann(0) # make sure no particles are placed at outer boundary\n\
\n\
if not domainClosed_s$ID$ or using_outflow_s$ID$:\n\
resetOutflow(flags=flags_s$ID$, phi=phi_s$ID$, parts=pp_s$ID$, index=gpi_s$ID$, indexSys=pindex_s$ID$)\n\
flags_s$ID$.updateFromLevelset(phi_s$ID$)\n\
\n\
# combine particle velocities with advected grid velocities\n\
if using_apic_s$ID$:\n\
apicMapPartsToMAC(flags=flags_s$ID$, vel=vel_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, cpx=pCx_pp$ID$, cpy=pCy_pp$ID$, cpz=pCz_pp$ID$)\n\
else:\n\
mapPartsToMAC(vel=velParts_s$ID$, flags=flags_s$ID$, velOld=velOld_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, weight=mapWeights_s$ID$)\n\
\n\
extrapolateMACFromWeight(vel=velParts_s$ID$, distance=2, weight=mapWeights_s$ID$)\n\
combineGridVel(vel=velParts_s$ID$, weight=mapWeights_s$ID$, combineVel=vel_s$ID$, phi=phi_s$ID$, narrowBand=combineBandWidth_s$ID$, thresh=0)\n\
velOld_s$ID$.copyFrom(vel_s$ID$)\n\
\n\
# forces & pressure solve\n\
addGravity(flags=flags_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, scale=False)\n\
\n\
mantaMsg('Adding external forces')\n\
addForceField(flags=flags_s$ID$, vel=vel_s$ID$, force=forces_s$ID$)\n\
\n\
extrapolateMACSimple(flags=flags_s$ID$, vel=vel_s$ID$, distance=2, intoObs=True if using_fractions_s$ID$ else False)\n\
\n\
# vel diffusion / viscosity!\n\
if using_diffusion_s$ID$:\n\
mantaMsg('Viscosity')\n\
# diffusion param for solve = const * dt / dx^2\n\
alphaV = kinViscosity_s$ID$ * s$ID$.timestep * float(res_s$ID$*res_s$ID$)\n\
setWallBcs(flags=flags_s$ID$, vel=vel_s$ID$, obvel=None if using_fractions_s$ID$ else obvel_s$ID$, phiObs=phiObs_s$ID$, fractions=fractions_s$ID$)\n\
cgSolveDiffusion(flags_s$ID$, vel_s$ID$, alphaV)\n\
\n\
mantaMsg('Curvature')\n\
getLaplacian(laplacian=curvature_s$ID$, grid=phi_s$ID$)\n\
curvature_s$ID$.clamp(-1.0, 1.0)\n\
\n\
setWallBcs(flags=flags_s$ID$, vel=vel_s$ID$, obvel=None if using_fractions_s$ID$ else obvel_s$ID$, phiObs=phiObs_s$ID$, fractions=fractions_s$ID$)\n\
if using_viscosity_s$ID$:\n\
viscosity_s$ID$.setConst(viscosityValue_s$ID$)\n\
applyViscosity(flags=flags_s$ID$, phi=phi_s$ID$, vel=vel_s$ID$, volumes=volumes_s$ID$, viscosity=viscosity_s$ID$)\n\
\n\
setWallBcs(flags=flags_s$ID$, vel=vel_s$ID$, obvel=None if using_fractions_s$ID$ else obvel_s$ID$, phiObs=phiObs_s$ID$, fractions=fractions_s$ID$)\n\
if using_guiding_s$ID$:\n\
mantaMsg('Guiding and pressure')\n\
PD_fluid_guiding(vel=vel_s$ID$, velT=velT_s$ID$, flags=flags_s$ID$, phi=phi_s$ID$, curv=curvature_s$ID$, surfTens=surfaceTension_s$ID$, fractions=fractions_s$ID$, weight=weightGuide_s$ID$, blurRadius=beta_sg$ID$, pressure=pressure_s$ID$, tau=tau_sg$ID$, sigma=sigma_sg$ID$, theta=theta_sg$ID$, zeroPressureFixing=domainClosed_s$ID$)\n\
else:\n\
mantaMsg('Pressure')\n\
solvePressure(flags=flags_s$ID$, vel=vel_s$ID$, pressure=pressure_s$ID$, curv=curvature_s$ID$, surfTens=surfaceTension_s$ID$, fractions=fractions_s$ID$, obvel=obvel_s$ID$ if using_fractions_s$ID$ else None, zeroPressureFixing=domainClosed_s$ID$)\n\
\n\
extrapolateMACSimple(flags=flags_s$ID$, vel=vel_s$ID$, distance=4, intoObs=True if using_fractions_s$ID$ else False)\n\
setWallBcs(flags=flags_s$ID$, vel=vel_s$ID$, obvel=None if using_fractions_s$ID$ else obvel_s$ID$, phiObs=phiObs_s$ID$, fractions=fractions_s$ID$)\n\
\n\
if not using_fractions_s$ID$:\n\
extrapolateMACSimple(flags=flags_s$ID$, vel=vel_s$ID$)\n\
\n\
# set source grids for resampling, used in adjustNumber!\n\
pVel_pp$ID$.setSource(grid=vel_s$ID$, isMAC=True)\n\
adjustNumber(parts=pp_s$ID$, vel=vel_s$ID$, flags=flags_s$ID$, minParticles=minParticles_s$ID$, maxParticles=maxParticles_s$ID$, phi=phi_s$ID$, exclude=phiObs_s$ID$, radiusFactor=radiusFactor_s$ID$, narrowBand=adjustedNarrowBandWidth_s$ID$)\n\
\n\
if using_apic_s$ID$:\n\
apicMapMACGridToParts(partVel=pVel_pp$ID$, cpx=pCx_pp$ID$, cpy=pCy_pp$ID$, cpz=pCz_pp$ID$, parts=pp_s$ID$, vel=vel_s$ID$, flags=flags_s$ID$)\n\
else:\n\
flipVelocityUpdate(vel=vel_s$ID$, velOld=velOld_s$ID$, flags=flags_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, flipRatio=flipRatio_s$ID$)\n";
const std::string liquid_step_mesh =
"\n\
def liquid_step_mesh_$ID$():\n\
mantaMsg('Liquid step mesh')\n\
\n\
# no upres: just use the loaded grids\n\
if upres_sm$ID$ <= 1:\n\
phi_sm$ID$.copyFrom(phi_s$ID$)\n\
\n\
# with upres: recreate grids\n\
else:\n\
interpolateGrid(target=phi_sm$ID$, source=phi_s$ID$)\n\
\n\
# create surface\n\
pp_sm$ID$.readParticles(pp_s$ID$)\n\
gridParticleIndex(parts=pp_sm$ID$, flags=flags_sm$ID$, indexSys=pindex_sm$ID$, index=gpi_sm$ID$)\n\
\n\
if using_final_mesh_s$ID$:\n\
mantaMsg('Liquid using improved particle levelset')\n\
improvedParticleLevelset(pp_sm$ID$, pindex_sm$ID$, flags_sm$ID$, gpi_sm$ID$, phiParts_sm$ID$, meshRadiusFactor_s$ID$, smoothenPos_s$ID$, smoothenNeg_s$ID$, concaveLower_s$ID$, concaveUpper_s$ID$)\n\
else:\n\
mantaMsg('Liquid using union particle levelset')\n\
unionParticleLevelset(pp_sm$ID$, pindex_sm$ID$, flags_sm$ID$, gpi_sm$ID$, phiParts_sm$ID$, meshRadiusFactor_s$ID$)\n\
\n\
phi_sm$ID$.addConst(1.) # shrink slightly\n\
phi_sm$ID$.join(phiParts_sm$ID$)\n\
extrapolateLsSimple(phi=phi_sm$ID$, distance=narrowBandWidth_s$ID$+2, inside=True)\n\
extrapolateLsSimple(phi=phi_sm$ID$, distance=3)\n\
phi_sm$ID$.setBoundNeumann(0) # make sure no particles are placed at outer boundary\n\
\n\
# Vert vel vector needs to pull data from vel grid with correct dim\n\
if using_speedvectors_s$ID$:\n\
interpolateMACGrid(target=vel_sm$ID$, source=vel_s$ID$)\n\
mVel_mesh$ID$.setSource(grid=vel_sm$ID$, isMAC=True)\n\
\n\
# Set 0.5 boundary at walls + account for extra wall thickness in fractions mode + account for grid scaling:\n\
# E.g. at upres=1 we expect 1 cell border (or 2 with fractions), at upres=2 we expect 2 cell border (or 4 with fractions), etc.\n\
# Use -1 since setBound() starts counting at 0 (and additional -1 for fractions to account for solid/fluid interface cells)\n\
phi_sm$ID$.setBound(value=0.5, boundaryWidth=(upres_sm$ID$*2)-2 if using_fractions_s$ID$ else upres_sm$ID$-1)\n\
phi_sm$ID$.createMesh(mesh_sm$ID$)\n";
const std::string liquid_step_particles =
"\n\
def liquid_step_particles_$ID$():\n\
mantaMsg('Secondary particles step')\n\
\n\
# no upres: just use the loaded grids\n\
if upres_sp$ID$ <= 1:\n\
vel_sp$ID$.copyFrom(velTmp_s$ID$)\n\
phiObs_sp$ID$.copyFrom(phiObs_s$ID$)\n\
phi_sp$ID$.copyFrom(phiTmp_s$ID$)\n\
phiOut_sp$ID$.copyFrom(phiOut_s$ID$)\n\
\n\
# with upres: recreate grids\n\
else:\n\
# create highres grids by interpolation\n\
interpolateMACGrid(target=vel_sp$ID$, source=velTmp_s$ID$)\n\
interpolateGrid(target=phiObs_sp$ID$, source=phiObs_s$ID$)\n\
interpolateGrid(target=phi_sp$ID$, source=phiTmp_s$ID$)\n\
interpolateGrid(target=phiOut_sp$ID$, source=phiOut_s$ID$)\n\
\n\
# phiIn not needed, bwidth to 0 because we are omitting flags.initDomain()\n\
setObstacleFlags(flags=flags_sp$ID$, phiObs=phiObs_sp$ID$, phiOut=phiOut_sp$ID$, phiIn=None, boundaryWidth=0)\n\
flags_sp$ID$.updateFromLevelset(levelset=phi_sp$ID$)\n\
\n\
# Actual secondary particle simulation\n\
flipComputeSecondaryParticlePotentials(potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, normal=normal_sp$ID$, phi=phi_sp$ID$, radius=pot_radius_sp$ID$, tauMinTA=tauMin_ta_sp$ID$, tauMaxTA=tauMax_ta_sp$ID$, tauMinWC=tauMin_wc_sp$ID$, tauMaxWC=tauMax_wc_sp$ID$, tauMinKE=tauMin_k_sp$ID$, tauMaxKE=tauMax_k_sp$ID$, scaleFromManta=ratioMetersToRes_s$ID$)\n\
flipSampleSecondaryParticles(mode='single', flags=flags_sp$ID$, v=vel_sp$ID$, pts_sec=ppSnd_sp$ID$, v_sec=pVelSnd_pp$ID$, l_sec=pLifeSnd_pp$ID$, lMin=lMin_sp$ID$, lMax=lMax_sp$ID$, potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, c_s=c_s_sp$ID$, c_b=c_b_sp$ID$, k_ta=k_ta_sp$ID$, k_wc=k_wc_sp$ID$)\n\
flipUpdateSecondaryParticles(mode='linear', pts_sec=ppSnd_sp$ID$, v_sec=pVelSnd_pp$ID$, l_sec=pLifeSnd_pp$ID$, f_sec=pForceSnd_pp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, neighborRatio=neighborRatio_sp$ID$, radius=update_radius_sp$ID$, gravity=gravity_s$ID$, scale=False, k_b=k_b_sp$ID$, k_d=k_d_sp$ID$, c_s=c_s_sp$ID$, c_b=c_b_sp$ID$)\n\
if using_snd_pushout_sp$ID$:\n\
pushOutofObs(parts=ppSnd_sp$ID$, flags=flags_sp$ID$, phiObs=phiObs_sp$ID$, shift=1.0)\n\
flipDeleteParticlesInObstacle(pts=ppSnd_sp$ID$, flags=flags_sp$ID$) # delete particles inside obstacle and outflow cells\n\
\n\
# Print debug information in the console\n\
if 0:\n\
debugGridInfo(flags=flags_sp$ID$, grid=trappedAir_sp$ID$, name='Trapped Air')\n\
debugGridInfo(flags=flags_sp$ID$, grid=waveCrest_sp$ID$, name='Wave Crest')\n\
debugGridInfo(flags=flags_sp$ID$, grid=kineticEnergy_sp$ID$, name='Kinetic Energy')\n";
//////////////////////////////////////////////////////////////////////
// IMPORT
//////////////////////////////////////////////////////////////////////
const std::string liquid_load_data =
"\n\
def liquid_load_data_$ID$(path, framenr, file_format, resumable):\n\
mantaMsg('Liquid load data')\n\
dict = { **fluid_data_dict_final_s$ID$, **fluid_data_dict_resume_s$ID$, **liquid_data_dict_final_s$ID$, **liquid_data_dict_resume_s$ID$ } if resumable else { **fluid_data_dict_final_s$ID$, **liquid_data_dict_final_s$ID$ }\n\
fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$)\n\
\n\
copyVec3ToReal(source=vel_s$ID$, targetX=x_vel_s$ID$, targetY=y_vel_s$ID$, targetZ=z_vel_s$ID$)\n";
const std::string liquid_load_mesh =
"\n\
def liquid_load_mesh_$ID$(path, framenr, file_format):\n\
mantaMsg('Liquid load mesh')\n\
dict = liquid_mesh_dict_s$ID$\n\
fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_mesh_s$ID$)\n\
\n\
def liquid_load_meshvel_$ID$(path, framenr, file_format):\n\
mantaMsg('Liquid load meshvel')\n\
dict = liquid_meshvel_dict_s$ID$\n\
fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_meshvel_s$ID$)\n";
const std::string liquid_load_particles =
"\n\
def liquid_load_particles_$ID$(path, framenr, file_format, resumable):\n\
mantaMsg('Liquid load particles')\n\
dict = { **liquid_particles_dict_final_s$ID$, **liquid_particles_dict_resume_s$ID$ } if resumable else { **liquid_particles_dict_final_s$ID$ }\n\
fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_particles_s$ID$)\n";
//////////////////////////////////////////////////////////////////////
// EXPORT
//////////////////////////////////////////////////////////////////////
const std::string liquid_save_data =
"\n\
def liquid_save_data_$ID$(path, framenr, file_format, resumable):\n\
mantaMsg('Liquid save data')\n\
dict = { **fluid_data_dict_final_s$ID$, **fluid_data_dict_resume_s$ID$, **liquid_data_dict_final_s$ID$, **liquid_data_dict_resume_s$ID$ } if resumable else { **fluid_data_dict_final_s$ID$, **liquid_data_dict_final_s$ID$ }\n\
if not withMPSave or isWindows:\n\
fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$)\n\
else:\n\
fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_data_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n";
const std::string liquid_save_mesh =
"\n\
def liquid_save_mesh_$ID$(path, framenr, file_format):\n\
mantaMsg('Liquid save mesh')\n\
dict = liquid_mesh_dict_s$ID$\n\
if not withMPSave or isWindows:\n\
fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_mesh_s$ID$)\n\
else:\n\
fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_mesh_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n\
\n\
def liquid_save_meshvel_$ID$(path, framenr, file_format):\n\
mantaMsg('Liquid save mesh vel')\n\
dict = liquid_meshvel_dict_s$ID$\n\
if not withMPSave or isWindows:\n\
fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format)\n\
else:\n\
fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n";
const std::string liquid_save_particles =
"\n\
def liquid_save_particles_$ID$(path, framenr, file_format, resumable):\n\
mantaMsg('Liquid save particles')\n\
dict = { **liquid_particles_dict_final_s$ID$, **liquid_particles_dict_resume_s$ID$ } if resumable else { **liquid_particles_dict_final_s$ID$ }\n\
if not withMPSave or isWindows:\n\
fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_particles_s$ID$)\n\
else:\n\
fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_particles_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n";
//////////////////////////////////////////////////////////////////////
// STANDALONE MODE
//////////////////////////////////////////////////////////////////////
const std::string liquid_standalone =
"\n\
# Helper function to call cache load functions\n\
def load_data(frame, cache_resumable):\n\
liquid_load_data_$ID$(os.path.join(cache_dir, 'data'), frame, file_format_data, cache_resumable)\n\
if using_sndparts_s$ID$:\n\
liquid_load_particles_$ID$(os.path.join(cache_dir, 'particles'), frame, file_format_data, cache_resumable)\n\
if using_mesh_s$ID$:\n\
liquid_load_mesh_$ID$(os.path.join(cache_dir, 'mesh'), frame, file_format_mesh)\n\
if using_guiding_s$ID$:\n\
fluid_load_guiding_$ID$(os.path.join(cache_dir, 'guiding'), frame, file_format_data)\n\
\n\
# Helper function to call step functions\n\
def step(frame):\n\
liquid_adaptive_step_$ID$(frame)\n\
if using_mesh_s$ID$:\n\
liquid_step_mesh_$ID$()\n\
if using_sndparts_s$ID$:\n\
liquid_step_particles_$ID$()\n";

View File

@@ -0,0 +1,598 @@
/* SPDX-FileCopyrightText: 2016 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_mantaflow
*/
#include <string>
//////////////////////////////////////////////////////////////////////
// VARIABLES
//////////////////////////////////////////////////////////////////////
const std::string smoke_variables =
"\n\
mantaMsg('Smoke variables low')\n\
preconditioner_s$ID$ = PcMGStatic\n\
using_colors_s$ID$ = $USING_COLORS$\n\
using_heat_s$ID$ = $USING_HEAT$\n\
using_fire_s$ID$ = $USING_FIRE$\n\
using_noise_s$ID$ = $USING_NOISE$\n\
vorticity_s$ID$ = $VORTICITY$\n\
buoyancy_dens_s$ID$ = float($BUOYANCY_ALPHA$) / float($FLUID_DOMAIN_SIZE$)\n\
buoyancy_heat_s$ID$ = float($BUOYANCY_BETA$) / float($FLUID_DOMAIN_SIZE$)\n\
dissolveSpeed_s$ID$ = $DISSOLVE_SPEED$\n\
using_logdissolve_s$ID$ = $USING_LOG_DISSOLVE$\n\
using_dissolve_s$ID$ = $USING_DISSOLVE$\n\
flameVorticity_s$ID$ = $FLAME_VORTICITY$\n\
burningRate_s$ID$ = $BURNING_RATE$\n\
flameSmoke_s$ID$ = $FLAME_SMOKE$\n\
ignitionTemp_s$ID$ = $IGNITION_TEMP$\n\
maxTemp_s$ID$ = $MAX_TEMP$\n\
flameSmokeColor_s$ID$ = vec3($FLAME_SMOKE_COLOR_X$,$FLAME_SMOKE_COLOR_Y$,$FLAME_SMOKE_COLOR_Z$)\n";
const std::string smoke_variables_noise =
"\n\
mantaMsg('Smoke variables noise')\n\
wltStrength_s$ID$ = $WLT_STR$\n\
uvs_s$ID$ = 2\n\
uvs_offset_s$ID$ = vec3($MIN_RESX$, $MIN_RESY$, $MIN_RESZ$)\n\
octaves_s$ID$ = int(math.log(upres_sn$ID$) / math.log(2.0) + 0.5) if (upres_sn$ID$ > 1) else 1\n";
const std::string smoke_wavelet_noise =
"\n\
# wavelet noise params\n\
wltnoise_sn$ID$.posScale = vec3(int($BASE_RESX$), int($BASE_RESY$), int($BASE_RESZ$)) * (1. / $NOISE_POSSCALE$)\n\
wltnoise_sn$ID$.timeAnim = $NOISE_TIMEANIM$\n";
const std::string smoke_with_heat =
"\n\
using_heat_s$ID$ = True\n";
const std::string smoke_with_colors =
"\n\
using_colors_s$ID$ = True\n";
const std::string smoke_with_fire =
"\n\
using_fire_s$ID$ = True\n";
//////////////////////////////////////////////////////////////////////
// GRIDS
//////////////////////////////////////////////////////////////////////
const std::string smoke_alloc =
"\n\
mantaMsg('Smoke alloc')\n\
shadow_s$ID$ = s$ID$.create(RealGrid, name='$NAME_SHADOW$', sparse=False)\n\
emission_s$ID$ = s$ID$.create(RealGrid, name='$NAME_EMISSION$', sparse=True)\n\
emissionIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_EMISSIONIN$')\n\
density_s$ID$ = s$ID$.create(RealGrid, name='$NAME_DENSITY$', sparse=True)\n\
densityIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_DENSITYIN$', sparse=True)\n\
heat_s$ID$ = None # allocated dynamically\n\
heatIn_s$ID$ = None\n\
flame_s$ID$ = None\n\
fuel_s$ID$ = None\n\
react_s$ID$ = None\n\
fuelIn_s$ID$ = None\n\
reactIn_s$ID$ = None\n\
color_r_s$ID$ = None\n\
color_g_s$ID$ = None\n\
color_b_s$ID$ = None\n\
color_r_in_s$ID$ = None\n\
color_g_in_s$ID$ = None\n\
color_b_in_s$ID$ = None\n\
\n\
# Set some initial values\n\
shadow_s$ID$.setConst(-1)\n\
\n\
# Keep track of important objects in dict to load them later on\n\
smoke_data_dict_final_s$ID$ = { 'density' : density_s$ID$, 'shadow' : shadow_s$ID$ }\n\
smoke_data_dict_resume_s$ID$ = { 'densityIn' : densityIn_s$ID$, 'emission' : emission_s$ID$ }\n";
const std::string smoke_alloc_noise =
"\n\
mantaMsg('Smoke alloc noise')\n\
vel_sn$ID$ = sn$ID$.create(MACGrid, name='$NAME_VELOCITY_NOISE$')\n\
density_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_DENSITY_NOISE$', sparse=True)\n\
phiIn_sn$ID$ = sn$ID$.create(LevelsetGrid, name='$NAME_PHIIN_NOISE$')\n\
phiOut_sn$ID$ = sn$ID$.create(LevelsetGrid, name='$NAME_PHIOUT_NOISE$')\n\
phiObs_sn$ID$ = sn$ID$.create(LevelsetGrid, name='$NAME_PHIOBS_NOISE$')\n\
flags_sn$ID$ = sn$ID$.create(FlagGrid, name='$NAME_FLAGS_NOISE$')\n\
tmpIn_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_TMPIN_NOISE$')\n\
emissionIn_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_EMISSIONIN_NOISE$')\n\
energy_s$ID$ = s$ID$.create(RealGrid, name='$NAME_ENERGY$')\n\
tmpFlags_s$ID$ = s$ID$.create(FlagGrid, name='$NAME_TMPFLAGS$')\n\
texture_u_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_U$')\n\
texture_v_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_V$')\n\
texture_w_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_W$')\n\
texture_u2_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_U2$')\n\
texture_v2_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_V2$')\n\
texture_w2_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_W2$')\n\
flame_sn$ID$ = None\n\
fuel_sn$ID$ = None\n\
react_sn$ID$ = None\n\
color_r_sn$ID$ = None\n\
color_g_sn$ID$ = None\n\
color_b_sn$ID$ = None\n\
wltnoise_sn$ID$ = sn$ID$.create(NoiseField, fixedSeed=265, loadFromFile=True)\n\
\n\
mantaMsg('Initializing UV Grids')\n\
uvGrid0_s$ID$ = s$ID$.create(VecGrid, name='$NAME_UV0$', sparse=False)\n\
uvGrid1_s$ID$ = s$ID$.create(VecGrid, name='$NAME_UV1$', sparse=False)\n\
resetUvGrid(target=uvGrid0_s$ID$, offset=uvs_offset_s$ID$)\n\
resetUvGrid(target=uvGrid1_s$ID$, offset=uvs_offset_s$ID$)\n\
\n\
# Sync UV and texture grids\n\
copyVec3ToReal(source=uvGrid0_s$ID$, targetX=texture_u_s$ID$, targetY=texture_v_s$ID$, targetZ=texture_w_s$ID$)\n\
copyVec3ToReal(source=uvGrid1_s$ID$, targetX=texture_u2_s$ID$, targetY=texture_v2_s$ID$, targetZ=texture_w2_s$ID$)\n\
\n\
# Keep track of important objects in dict to load them later on\n\
smoke_noise_dict_final_s$ID$ = { 'density_noise' : density_sn$ID$ }\n\
smoke_noise_dict_resume_s$ID$ = { 'uv0_noise' : uvGrid0_s$ID$, 'uv1_noise' : uvGrid1_s$ID$ }\n";
//////////////////////////////////////////////////////////////////////
// ADDITIONAL GRIDS
//////////////////////////////////////////////////////////////////////
const std::string smoke_alloc_colors =
"\n\
# Sanity check, clear grids first\n\
if 'color_r_s$ID$' in globals(): del color_r_s$ID$\n\
if 'color_g_s$ID$' in globals(): del color_g_s$ID$\n\
if 'color_b_s$ID$' in globals(): del color_b_s$ID$\n\
\n\
mantaMsg('Allocating colors')\n\
color_r_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORR$', sparse=True)\n\
color_g_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORG$', sparse=True)\n\
color_b_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORB$', sparse=True)\n\
color_r_in_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORRIN$', sparse=True)\n\
color_g_in_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORGIN$', sparse=True)\n\
color_b_in_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORBIN$', sparse=True)\n\
\n\
# Add objects to dict to load them later on\n\
if 'smoke_data_dict_final_s$ID$' in globals():\n\
smoke_data_dict_final_s$ID$.update(color_r=color_r_s$ID$, color_g=color_g_s$ID$, color_b=color_b_s$ID$)\n\
if 'smoke_data_dict_resume_s$ID$' in globals():\n\
smoke_data_dict_resume_s$ID$.update(color_r_in=color_r_in_s$ID$, color_g_in=color_g_in_s$ID$, color_b_in=color_b_in_s$ID$)\n";
const std::string smoke_alloc_colors_noise =
"\n\
# Sanity check, clear grids first\n\
if 'color_r_sn$ID$' in globals(): del color_r_sn$ID$\n\
if 'color_g_sn$ID$' in globals(): del color_g_sn$ID$\n\
if 'color_b_sn$ID$' in globals(): del color_b_sn$ID$\n\
\n\
mantaMsg('Allocating colors noise')\n\
color_r_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORR_NOISE$', sparse=True)\n\
color_g_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORG_NOISE$', sparse=True)\n\
color_b_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORB_NOISE$', sparse=True)\n\
\n\
# Add objects to dict to load them later on\n\
if 'smoke_noise_dict_final_s$ID$' in globals():\n\
smoke_noise_dict_final_s$ID$.update(color_r_noise=color_r_sn$ID$, color_g_noise=color_g_sn$ID$, color_b_noise=color_b_sn$ID$)\n";
const std::string smoke_init_colors =
"\n\
mantaMsg('Initializing colors')\n\
color_r_s$ID$.copyFrom(density_s$ID$) \n\
color_r_s$ID$.multConst($COLOR_R$) \n\
color_g_s$ID$.copyFrom(density_s$ID$) \n\
color_g_s$ID$.multConst($COLOR_G$) \n\
color_b_s$ID$.copyFrom(density_s$ID$) \n\
color_b_s$ID$.multConst($COLOR_B$)\n";
const std::string smoke_init_colors_noise =
"\n\
mantaMsg('Initializing colors noise')\n\
color_r_sn$ID$.copyFrom(density_sn$ID$) \n\
color_r_sn$ID$.multConst($COLOR_R$) \n\
color_g_sn$ID$.copyFrom(density_sn$ID$) \n\
color_g_sn$ID$.multConst($COLOR_G$) \n\
color_b_sn$ID$.copyFrom(density_sn$ID$) \n\
color_b_sn$ID$.multConst($COLOR_B$)\n";
const std::string smoke_alloc_heat =
"\n\
# Sanity check, clear grids first\n\
if 'heat_s$ID$' in globals(): del heat_s$ID$\n\
if 'heatIn_s$ID$' in globals(): del heatIn_s$ID$\n\
\n\
mantaMsg('Allocating heat')\n\
heat_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEMPERATURE$', sparse=True)\n\
heatIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEMPERATUREIN$', sparse=True)\n\
\n\
# Add objects to dict to load them later on\n\
if 'smoke_data_dict_final_s$ID$' in globals():\n\
smoke_data_dict_final_s$ID$.update(heat=heat_s$ID$)\n\
if 'smoke_data_dict_resume_s$ID$' in globals():\n\
smoke_data_dict_resume_s$ID$.update(heatIn=heatIn_s$ID$)\n";
const std::string smoke_alloc_fire =
"\n\
# Sanity check, clear grids first\n\
if 'flame_s$ID$' in globals(): del flame_s$ID$\n\
if 'fuel_s$ID$' in globals(): del fuel_s$ID$\n\
if 'react_s$ID$' in globals(): del react_s$ID$\n\
if 'fuelIn_s$ID$' in globals(): del fuelIn_s$ID$\n\
if 'reactIn_s$ID$' in globals(): del reactIn_s$ID$\n\
\n\
mantaMsg('Allocating fire')\n\
flame_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FLAME$', sparse=True)\n\
fuel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FUEL$', sparse=True)\n\
react_s$ID$ = s$ID$.create(RealGrid, name='$NAME_REACT$', sparse=True)\n\
fuelIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FUELIN$', sparse=True)\n\
reactIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_REACTIN$', sparse=True)\n\
\n\
# Add objects to dict to load them later on\n\
if 'smoke_data_dict_final_s$ID$' in globals():\n\
smoke_data_dict_final_s$ID$.update(flame=flame_s$ID$)\n\
if 'smoke_data_dict_resume_s$ID$' in globals():\n\
smoke_data_dict_resume_s$ID$.update(fuel=fuel_s$ID$, react=react_s$ID$, fuelIn=fuelIn_s$ID$, reactIn=reactIn_s$ID$)\n";
const std::string smoke_alloc_fire_noise =
"\n\
# Sanity check, clear grids first\n\
if 'flame_sn$ID$' in globals(): del flame_sn$ID$\n\
if 'fuel_sn$ID$' in globals(): del fuel_sn$ID$\n\
if 'react_sn$ID$' in globals(): del react_sn$ID$\n\
\n\
mantaMsg('Allocating fire noise')\n\
flame_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_FLAME_NOISE$', sparse=True)\n\
fuel_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_FUEL_NOISE$', sparse=True)\n\
react_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_REACT_NOISE$', sparse=True)\n\
\n\
# Add objects to dict to load them later on\n\
if 'smoke_noise_dict_final_s$ID$' in globals():\n\
smoke_noise_dict_final_s$ID$.update(flame_noise=flame_sn$ID$)\n\
if 'smoke_noise_dict_resume_s$ID$' in globals():\n\
smoke_noise_dict_resume_s$ID$.update(fuel_noise=fuel_sn$ID$, react_noise=react_sn$ID$)\n";
//////////////////////////////////////////////////////////////////////
// STEP FUNCTIONS
//////////////////////////////////////////////////////////////////////
const std::string smoke_adaptive_step =
"\n\
def smoke_adaptive_step_$ID$(framenr):\n\
mantaMsg('Manta step, frame ' + str(framenr))\n\
s$ID$.frame = framenr\n\
\n\
fluid_pre_step_$ID$()\n\
\n\
flags_s$ID$.initDomain(boundaryWidth=0, phiWalls=phiObs_s$ID$, outflow=boundConditions_s$ID$)\n\
\n\
if using_obstacle_s$ID$:\n\
mantaMsg('Extrapolating object velocity')\n\
# ensure velocities inside of obs object, slightly add obvels outside of obs object\n\
# extrapolate with phiObsIn before joining (static) phiObsSIn grid to prevent flows into static obs\n\
extrapolateVec3Simple(vel=obvelC_s$ID$, phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
extrapolateVec3Simple(vel=obvelC_s$ID$, phi=phiObsIn_s$ID$, distance=3, inside=False)\n\
resampleVec3ToMac(source=obvelC_s$ID$, target=obvel_s$ID$)\n\
\n\
mantaMsg('Initializing obstacle levelset')\n\
phiObsIn_s$ID$.join(phiObsSIn_s$ID$) # Join static obstacle map\n\
phiObsIn_s$ID$.floodFill(boundaryWidth=1)\n\
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=3, inside=False)\n\
phiObs_s$ID$.join(phiObsIn_s$ID$)\n\
\n\
# Additional sanity check: fill holes in phiObs which can result after joining with phiObsIn\n\
phiObs_s$ID$.floodFill(boundaryWidth=1)\n\
extrapolateLsSimple(phi=phiObs_s$ID$, distance=6, inside=True)\n\
extrapolateLsSimple(phi=phiObs_s$ID$, distance=3, inside=False)\n\
\n\
mantaMsg('Initializing fluid levelset')\n\
phiIn_s$ID$.join(phiSIn_s$ID$) # Join static flow map\n\
extrapolateLsSimple(phi=phiIn_s$ID$, distance=6, inside=True)\n\
extrapolateLsSimple(phi=phiIn_s$ID$, distance=3, inside=False)\n\
\n\
if using_outflow_s$ID$:\n\
phiOutIn_s$ID$.join(phiOutSIn_s$ID$) # Join static outflow map\n\
phiOut_s$ID$.join(phiOutIn_s$ID$)\n\
\n\
setObstacleFlags(flags=flags_s$ID$, phiObs=phiObs_s$ID$, phiOut=phiOut_s$ID$, phiIn=phiIn_s$ID$, boundaryWidth=1)\n\
flags_s$ID$.fillGrid()\n\
\n\
# reset emission accumulation at the beginning of an adaptive frame\n\
if not s$ID$.timePerFrame:\n\
emission_s$ID$.setConst(0.)\n\
# accumulate emission value per adaptive step for later use in noise computation\n\
emission_s$ID$.join(emissionIn_s$ID$)\n\
\n\
applyEmission(flags=flags_s$ID$, target=density_s$ID$, source=densityIn_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
if using_heat_s$ID$:\n\
applyEmission(flags=flags_s$ID$, target=heat_s$ID$, source=heatIn_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
\n\
if using_colors_s$ID$:\n\
applyEmission(flags=flags_s$ID$, target=color_r_s$ID$, source=color_r_in_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
applyEmission(flags=flags_s$ID$, target=color_g_s$ID$, source=color_g_in_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
applyEmission(flags=flags_s$ID$, target=color_b_s$ID$, source=color_b_in_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
\n\
if using_fire_s$ID$:\n\
applyEmission(flags=flags_s$ID$, target=fuel_s$ID$, source=fuelIn_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
applyEmission(flags=flags_s$ID$, target=react_s$ID$, source=reactIn_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
\n\
mantaMsg('Smoke step / s$ID$.frame: ' + str(s$ID$.frame))\n\
if using_fire_s$ID$:\n\
process_burn_$ID$()\n\
smoke_step_$ID$()\n\
if using_fire_s$ID$:\n\
update_flame_$ID$()\n\
\n\
s$ID$.step()\n\
\n\
fluid_post_step_$ID$()\n";
const std::string smoke_step =
"\n\
def smoke_step_$ID$():\n\
mantaMsg('Smoke step low')\n\
\n\
# save original state for later (used during noise creation)\n\
velTmp_s$ID$.copyFrom(vel_s$ID$)\n\
\n\
if using_dissolve_s$ID$:\n\
mantaMsg('Dissolving smoke')\n\
dissolveSmoke(flags=flags_s$ID$, density=density_s$ID$, heat=heat_s$ID$, red=color_r_s$ID$, green=color_g_s$ID$, blue=color_b_s$ID$, \
speed=dissolveSpeed_s$ID$, logFalloff=using_logdissolve_s$ID$, dissolveScale=s$ID$.timestep / frameLengthUnscaled_s$ID$)\n\
\n\
mantaMsg('Advecting density')\n\
advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=density_s$ID$, order=2)\n\
\n\
if using_heat_s$ID$:\n\
mantaMsg('Advecting heat')\n\
advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=heat_s$ID$, order=2)\n\
\n\
if using_fire_s$ID$:\n\
mantaMsg('Advecting fire')\n\
advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=fuel_s$ID$, order=2)\n\
advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=react_s$ID$, order=2)\n\
\n\
if using_colors_s$ID$:\n\
mantaMsg('Advecting colors')\n\
advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=color_r_s$ID$, order=2)\n\
advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=color_g_s$ID$, order=2)\n\
advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=color_b_s$ID$, order=2)\n\
\n\
mantaMsg('Advecting velocity')\n\
advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=vel_s$ID$, order=2)\n\
\n\
if not domainClosed_s$ID$ or using_outflow_s$ID$:\n\
resetOutflow(flags=flags_s$ID$, real=density_s$ID$)\n\
\n\
mantaMsg('Vorticity')\n\
if using_fire_s$ID$:\n\
flame_s$ID$.copyFrom(fuel_s$ID$) # temporarily misuse flame grid as vorticity storage\n\
flame_s$ID$.multConst(flameVorticity_s$ID$ * s$ID$.timestep / frameLengthUnscaled_s$ID$)\n\
vorticityConfinement(vel=vel_s$ID$, flags=flags_s$ID$, strength=vorticity_s$ID$ * s$ID$.timestep / frameLengthUnscaled_s$ID$, strengthCell=flame_s$ID$ if using_fire_s$ID$ else None)\n\
\n\
if using_heat_s$ID$:\n\
mantaMsg('Adding heat buoyancy')\n\
addBuoyancy(flags=flags_s$ID$, density=heat_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_heat_s$ID$, scale=False)\n\
mantaMsg('Adding buoyancy')\n\
addBuoyancy(flags=flags_s$ID$, density=density_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_dens_s$ID$, scale=False)\n\
\n\
mantaMsg('Adding forces')\n\
addForceField(flags=flags_s$ID$, vel=vel_s$ID$, force=forces_s$ID$)\n\
\n\
# Cells inside obstacle should not contain any density, fire, etc.\n\
if deleteInObstacle_s$ID$:\n\
resetInObstacle(flags=flags_s$ID$, density=density_s$ID$, vel=vel_s$ID$, heat=heat_s$ID$, fuel=fuel_s$ID$, flame=flame_s$ID$, red=color_r_s$ID$, green=color_g_s$ID$, blue=color_b_s$ID$)\n\
\n\
# add initial velocity\n\
if using_invel_s$ID$:\n\
# Using cell centered invels, will be converted to MAC within the function\n\
setInitialVelocity(flags=flags_s$ID$, vel=vel_s$ID$, invel=invelC_s$ID$)\n\
\n\
mantaMsg('Walls')\n\
setWallBcs(flags=flags_s$ID$, vel=vel_s$ID$, obvel=obvel_s$ID$ if using_obstacle_s$ID$ else None)\n\
\n\
preconditioner_s$ID$ = PcMGDynamic if using_obstacle_s$ID$ and obvel_s$ID$.getMax() > 0 else PcMGStatic\n\
mantaMsg('Using preconditioner: ' + str(preconditioner_s$ID$))\n\
if using_guiding_s$ID$:\n\
mantaMsg('Guiding and pressure')\n\
PD_fluid_guiding(vel=vel_s$ID$, velT=velT_s$ID$, flags=flags_s$ID$, weight=weightGuide_s$ID$, blurRadius=beta_sg$ID$, pressure=pressure_s$ID$, tau=tau_sg$ID$, sigma=sigma_sg$ID$, theta=theta_sg$ID$, preconditioner=preconditioner_s$ID$, zeroPressureFixing=domainClosed_s$ID$)\n\
else:\n\
mantaMsg('Pressure')\n\
solvePressure(flags=flags_s$ID$, vel=vel_s$ID$, pressure=pressure_s$ID$, preconditioner=preconditioner_s$ID$, zeroPressureFixing=domainClosed_s$ID$) # closed domains require pressure fixing\n\
\n\
def process_burn_$ID$():\n\
mantaMsg('Process burn')\n\
processBurn(fuel=fuel_s$ID$, density=density_s$ID$, react=react_s$ID$, red=color_r_s$ID$, green=color_g_s$ID$, blue=color_b_s$ID$, heat=heat_s$ID$, burningRate=burningRate_s$ID$, flameSmoke=flameSmoke_s$ID$, ignitionTemp=ignitionTemp_s$ID$, maxTemp=maxTemp_s$ID$, flameSmokeColor=flameSmokeColor_s$ID$)\n\
\n\
def update_flame_$ID$():\n\
mantaMsg('Update flame')\n\
updateFlame(react=react_s$ID$, flame=flame_s$ID$)\n";
const std::string smoke_step_noise =
"\n\
def smoke_step_noise_$ID$(framenr):\n\
mantaMsg('Manta step noise, frame ' + str(framenr))\n\
sn$ID$.frame = framenr\n\
\n\
copyRealToVec3(sourceX=texture_u_s$ID$, sourceY=texture_v_s$ID$, sourceZ=texture_w_s$ID$, target=uvGrid0_s$ID$)\n\
copyRealToVec3(sourceX=texture_u2_s$ID$, sourceY=texture_v2_s$ID$, sourceZ=texture_w2_s$ID$, target=uvGrid1_s$ID$)\n\
\n\
flags_sn$ID$.initDomain(boundaryWidth=0, phiWalls=phiObs_sn$ID$, outflow=boundConditions_s$ID$)\n\
\n\
mantaMsg('Interpolating grids')\n\
# Join big obstacle levelset after initDomain() call as it overwrites everything in phiObs\n\
if using_obstacle_s$ID$:\n\
phiIn_sn$ID$.copyFrom(phiObsIn_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(target=phiIn_sn$ID$, source=phiObsIn_s$ID$) # mis-use phiIn_sn\n\
phiObs_sn$ID$.join(phiIn_sn$ID$)\n\
if using_outflow_s$ID$:\n\
phiOut_sn$ID$.copyFrom(phiOut_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(target=phiOut_sn$ID$, source=phiOut_s$ID$)\n\
phiIn_sn$ID$.copyFrom(phiIn_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(target=phiIn_sn$ID$, source=phiIn_s$ID$)\n\
vel_sn$ID$.copyFrom(velTmp_s$ID$) if upres_sn$ID$ <= 1 else interpolateMACGrid(target=vel_sn$ID$, source=velTmp_s$ID$)\n\
\n\
setObstacleFlags(flags=flags_sn$ID$, phiObs=phiObs_sn$ID$, phiOut=phiOut_sn$ID$, phiIn=phiIn_sn$ID$, boundaryWidth=1)\n\
flags_sn$ID$.fillGrid()\n\
\n\
# Interpolate emission grids and apply them to big noise grids\n\
tmpIn_sn$ID$.copyFrom(densityIn_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=densityIn_s$ID$, target=tmpIn_sn$ID$)\n\
emissionIn_sn$ID$.copyFrom(emission_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=emission_s$ID$, target=emissionIn_sn$ID$)\n\
\n\
# Higher-res noise grid needs scaled emission values\n\
tmpIn_sn$ID$.multConst(float(upres_sn$ID$))\n\
applyEmission(flags=flags_sn$ID$, target=density_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
\n\
if using_colors_s$ID$:\n\
tmpIn_sn$ID$.copyFrom(color_r_in_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=color_r_in_s$ID$, target=tmpIn_sn$ID$)\n\
applyEmission(flags=flags_sn$ID$, target=color_r_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
tmpIn_sn$ID$.copyFrom(color_g_in_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=color_g_in_s$ID$, target=tmpIn_sn$ID$)\n\
applyEmission(flags=flags_sn$ID$, target=color_g_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
tmpIn_sn$ID$.copyFrom(color_b_in_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=color_b_in_s$ID$, target=tmpIn_sn$ID$)\n\
applyEmission(flags=flags_sn$ID$, target=color_b_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
\n\
if using_fire_s$ID$:\n\
tmpIn_sn$ID$.copyFrom(fuelIn_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=fuelIn_s$ID$, target=tmpIn_sn$ID$)\n\
applyEmission(flags=flags_sn$ID$, target=fuel_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
tmpIn_sn$ID$.copyFrom(reactIn_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=reactIn_s$ID$, target=tmpIn_sn$ID$)\n\
applyEmission(flags=flags_sn$ID$, target=react_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
\n\
mantaMsg('Noise step / sn$ID$.frame: ' + str(sn$ID$.frame))\n\
if using_fire_s$ID$:\n\
process_burn_noise_$ID$()\n\
step_noise_$ID$()\n\
if using_fire_s$ID$:\n\
update_flame_noise_$ID$()\n\
\n\
sn$ID$.step()\n\
\n\
copyVec3ToReal(source=uvGrid0_s$ID$, targetX=texture_u_s$ID$, targetY=texture_v_s$ID$, targetZ=texture_w_s$ID$)\n\
copyVec3ToReal(source=uvGrid1_s$ID$, targetX=texture_u2_s$ID$, targetY=texture_v2_s$ID$, targetZ=texture_w2_s$ID$)\n\
\n\
def step_noise_$ID$():\n\
mantaMsg('Smoke step noise')\n\
\n\
if using_dissolve_s$ID$:\n\
mantaMsg('Dissolving noise')\n\
dissolveSmoke(flags=flags_sn$ID$, density=density_sn$ID$, heat=None, red=color_r_sn$ID$, green=color_g_sn$ID$, blue=color_b_sn$ID$, \
speed=dissolveSpeed_s$ID$, logFalloff=using_logdissolve_s$ID$, dissolveScale=s$ID$.timestep / frameLengthUnscaled_s$ID$)\n\
\n\
mantaMsg('Advecting UVs and updating UV weight')\n\
advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=uvGrid0_s$ID$, order=2)\n\
updateUvWeight(resetTime=sn$ID$.timestep*10.0 , index=0, numUvs=uvs_s$ID$, uv=uvGrid0_s$ID$, offset=uvs_offset_s$ID$)\n\
advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=uvGrid1_s$ID$, order=2)\n\
updateUvWeight(resetTime=sn$ID$.timestep*10.0 , index=1, numUvs=uvs_s$ID$, uv=uvGrid1_s$ID$, offset=uvs_offset_s$ID$)\n\
\n\
if not domainClosed_s$ID$ or using_outflow_s$ID$:\n\
resetOutflow(flags=flags_sn$ID$, real=density_sn$ID$)\n\
\n\
mantaMsg('Energy')\n\
computeEnergy(flags=flags_s$ID$, vel=vel_s$ID$, energy=energy_s$ID$)\n\
\n\
tmpFlags_s$ID$.copyFrom(flags_s$ID$)\n\
extrapolateSimpleFlags(flags=flags_s$ID$, val=tmpFlags_s$ID$, distance=2, flagFrom=FlagObstacle, flagTo=FlagFluid)\n\
extrapolateSimpleFlags(flags=tmpFlags_s$ID$, val=energy_s$ID$, distance=6, flagFrom=FlagFluid, flagTo=FlagObstacle)\n\
computeWaveletCoeffs(energy_s$ID$)\n\
\n\
sStr_s$ID$ = 1.0 * wltStrength_s$ID$\n\
sPos_s$ID$ = 2.0\n\
\n\
mantaMsg('Applying noise vec')\n\
for o in range(octaves_s$ID$):\n\
uvWeight_s$ID$ = getUvWeight(uvGrid0_s$ID$)\n\
applyNoiseVec3(flags=flags_sn$ID$, target=vel_sn$ID$, noise=wltnoise_sn$ID$, scale=sStr_s$ID$ * uvWeight_s$ID$, scaleSpatial=sPos_s$ID$ , weight=energy_s$ID$, uv=uvGrid0_s$ID$)\n\
uvWeight_s$ID$ = getUvWeight(uvGrid1_s$ID$)\n\
applyNoiseVec3(flags=flags_sn$ID$, target=vel_sn$ID$, noise=wltnoise_sn$ID$, scale=sStr_s$ID$ * uvWeight_s$ID$, scaleSpatial=sPos_s$ID$ , weight=energy_s$ID$, uv=uvGrid1_s$ID$)\n\
\n\
sStr_s$ID$ *= 0.06 # magic kolmogorov factor \n\
sPos_s$ID$ *= 2.0 \n\
\n\
for substep in range(int(upres_sn$ID$)):\n\
if using_colors_s$ID$: \n\
mantaMsg('Advecting colors noise')\n\
advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=color_r_sn$ID$, order=2)\n\
advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=color_g_sn$ID$, order=2)\n\
advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=color_b_sn$ID$, order=2)\n\
\n\
if using_fire_s$ID$: \n\
mantaMsg('Advecting fire noise')\n\
advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=fuel_sn$ID$, order=2)\n\
advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=react_sn$ID$, order=2)\n\
\n\
mantaMsg('Advecting density noise')\n\
advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=density_sn$ID$, order=2)\n\
\n\
def process_burn_noise_$ID$():\n\
mantaMsg('Process burn noise')\n\
processBurn(fuel=fuel_sn$ID$, density=density_sn$ID$, react=react_sn$ID$, red=color_r_sn$ID$, green=color_g_sn$ID$, blue=color_b_sn$ID$, burningRate=burningRate_s$ID$, flameSmoke=flameSmoke_s$ID$, ignitionTemp=ignitionTemp_s$ID$, maxTemp=maxTemp_s$ID$, flameSmokeColor=flameSmokeColor_s$ID$)\n\
\n\
def update_flame_noise_$ID$():\n\
mantaMsg('Update flame noise')\n\
updateFlame(react=react_sn$ID$, flame=flame_sn$ID$)\n";
//////////////////////////////////////////////////////////////////////
// IMPORT
//////////////////////////////////////////////////////////////////////
const std::string smoke_load_data =
"\n\
def smoke_load_data_$ID$(path, framenr, file_format, resumable):\n\
mantaMsg('Smoke load data')\n\
dict = { **fluid_data_dict_final_s$ID$, **fluid_data_dict_resume_s$ID$, **smoke_data_dict_final_s$ID$, **smoke_data_dict_resume_s$ID$ } if resumable else { **fluid_data_dict_final_s$ID$, **smoke_data_dict_final_s$ID$ }\n\
fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$)\n\
\n\
copyVec3ToReal(source=vel_s$ID$, targetX=x_vel_s$ID$, targetY=y_vel_s$ID$, targetZ=z_vel_s$ID$)\n";
const std::string smoke_load_noise =
"\n\
def smoke_load_noise_$ID$(path, framenr, file_format, resumable):\n\
mantaMsg('Smoke load noise')\n\
dict = { **smoke_noise_dict_final_s$ID$, **smoke_noise_dict_resume_s$ID$ } if resumable else { **smoke_noise_dict_final_s$ID$ } \n\
fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_noise_s$ID$)\n\
\n\
if resumable:\n\
# Fill up xyz texture grids, important when resuming a bake\n\
copyVec3ToReal(source=uvGrid0_s$ID$, targetX=texture_u_s$ID$, targetY=texture_v_s$ID$, targetZ=texture_w_s$ID$)\n\
copyVec3ToReal(source=uvGrid1_s$ID$, targetX=texture_u2_s$ID$, targetY=texture_v2_s$ID$, targetZ=texture_w2_s$ID$)\n";
//////////////////////////////////////////////////////////////////////
// EXPORT
//////////////////////////////////////////////////////////////////////
const std::string smoke_save_data =
"\n\
def smoke_save_data_$ID$(path, framenr, file_format, resumable):\n\
mantaMsg('Smoke save data')\n\
start_time = time.time()\n\
dict = { **fluid_data_dict_final_s$ID$, **fluid_data_dict_resume_s$ID$, **smoke_data_dict_final_s$ID$, **smoke_data_dict_resume_s$ID$ } if resumable else { **fluid_data_dict_final_s$ID$, **smoke_data_dict_final_s$ID$ } \n\
if not withMPSave or isWindows:\n\
fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$, clipGrid=density_s$ID$)\n\
else:\n\
fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_data_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n\
mantaMsg('--- Save: %s seconds ---' % (time.time() - start_time))\n";
const std::string smoke_save_noise =
"\n\
def smoke_save_noise_$ID$(path, framenr, file_format, resumable):\n\
mantaMsg('Smoke save noise')\n\
dict = { **smoke_noise_dict_final_s$ID$, **smoke_noise_dict_resume_s$ID$ } if resumable else { **smoke_noise_dict_final_s$ID$ } \n\
if not withMPSave or isWindows:\n\
fluid_file_export_s$ID$(dict=dict, framenr=framenr, file_format=file_format, path=path, file_name=file_noise_s$ID$, clipGrid=density_sn$ID$)\n\
else:\n\
fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_noise_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n";
//////////////////////////////////////////////////////////////////////
// STANDALONE MODE
//////////////////////////////////////////////////////////////////////
const std::string smoke_standalone =
"\n\
# Helper function to call cache load functions\n\
def load_data(frame, cache_resumable):\n\
smoke_load_data_$ID$(os.path.join(cache_dir, 'data'), frame, file_format_data, cache_resumable)\n\
if using_noise_s$ID$:\n\
smoke_load_noise_$ID$(os.path.join(cache_dir, 'noise'), frame, file_format_data, cache_resumable)\n\
if using_guiding_s$ID$:\n\
fluid_load_guiding_$ID$(os.path.join(cache_dir, 'guiding'), frame, file_format_data)\n\
\n\
# Helper function to call step functions\n\
def step(frame):\n\
smoke_adaptive_step_$ID$(frame)\n\
if using_noise_s$ID$:\n\
smoke_step_noise_$ID$(frame)\n";