Blender  V2.93
smoke_script.h
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2016 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include <string>
25 
27 // VARIABLES
29 
30 const std::string smoke_variables =
31  "\n\
32 mantaMsg('Smoke variables low')\n\
33 preconditioner_s$ID$ = PcMGStatic\n\
34 using_colors_s$ID$ = $USING_COLORS$\n\
35 using_heat_s$ID$ = $USING_HEAT$\n\
36 using_fire_s$ID$ = $USING_FIRE$\n\
37 using_noise_s$ID$ = $USING_NOISE$\n\
38 vorticity_s$ID$ = $VORTICITY$\n\
39 buoyancy_dens_s$ID$ = float($BUOYANCY_ALPHA$) / float($FLUID_DOMAIN_SIZE$)\n\
40 buoyancy_heat_s$ID$ = float($BUOYANCY_BETA$) / float($FLUID_DOMAIN_SIZE$)\n\
41 dissolveSpeed_s$ID$ = $DISSOLVE_SPEED$\n\
42 using_logdissolve_s$ID$ = $USING_LOG_DISSOLVE$\n\
43 using_dissolve_s$ID$ = $USING_DISSOLVE$\n\
44 flameVorticity_s$ID$ = $FLAME_VORTICITY$\n\
45 burningRate_s$ID$ = $BURNING_RATE$\n\
46 flameSmoke_s$ID$ = $FLAME_SMOKE$\n\
47 ignitionTemp_s$ID$ = $IGNITION_TEMP$\n\
48 maxTemp_s$ID$ = $MAX_TEMP$\n\
49 flameSmokeColor_s$ID$ = vec3($FLAME_SMOKE_COLOR_X$,$FLAME_SMOKE_COLOR_Y$,$FLAME_SMOKE_COLOR_Z$)\n";
50 
51 const std::string smoke_variables_noise =
52  "\n\
53 mantaMsg('Smoke variables noise')\n\
54 wltStrength_s$ID$ = $WLT_STR$\n\
55 uvs_s$ID$ = 2\n\
56 uvs_offset_s$ID$ = vec3($MIN_RESX$, $MIN_RESY$, $MIN_RESZ$)\n\
57 octaves_s$ID$ = int(math.log(upres_sn$ID$) / math.log(2.0) + 0.5) if (upres_sn$ID$ > 1) else 1\n";
58 
59 const std::string smoke_wavelet_noise =
60  "\n\
61 # wavelet noise params\n\
62 wltnoise_sn$ID$.posScale = vec3(int($BASE_RESX$), int($BASE_RESY$), int($BASE_RESZ$)) * (1. / $NOISE_POSSCALE$)\n\
63 wltnoise_sn$ID$.timeAnim = $NOISE_TIMEANIM$\n";
64 
65 const std::string smoke_with_heat =
66  "\n\
67 using_heat_s$ID$ = True\n";
68 
69 const std::string smoke_with_colors =
70  "\n\
71 using_colors_s$ID$ = True\n";
72 
73 const std::string smoke_with_fire =
74  "\n\
75 using_fire_s$ID$ = True\n";
76 
78 // GRIDS
80 
81 const std::string smoke_alloc =
82  "\n\
83 mantaMsg('Smoke alloc')\n\
84 shadow_s$ID$ = s$ID$.create(RealGrid, name='$NAME_SHADOW$', sparse=False)\n\
85 emission_s$ID$ = s$ID$.create(RealGrid, name='$NAME_EMISSION$', sparse=True)\n\
86 emissionIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_EMISSIONIN$')\n\
87 density_s$ID$ = s$ID$.create(RealGrid, name='$NAME_DENSITY$', sparse=True)\n\
88 densityIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_DENSITYIN$', sparse=True)\n\
89 heat_s$ID$ = None # allocated dynamically\n\
90 heatIn_s$ID$ = None\n\
91 flame_s$ID$ = None\n\
92 fuel_s$ID$ = None\n\
93 react_s$ID$ = None\n\
94 fuelIn_s$ID$ = None\n\
95 reactIn_s$ID$ = None\n\
96 color_r_s$ID$ = None\n\
97 color_g_s$ID$ = None\n\
98 color_b_s$ID$ = None\n\
99 color_r_in_s$ID$ = None\n\
100 color_g_in_s$ID$ = None\n\
101 color_b_in_s$ID$ = None\n\
102 \n\
103 # Set some initial values\n\
104 shadow_s$ID$.setConst(-1)\n\
105 \n\
106 # Keep track of important objects in dict to load them later on\n\
107 smoke_data_dict_final_s$ID$ = { 'density' : density_s$ID$, 'shadow' : shadow_s$ID$ }\n\
108 smoke_data_dict_resume_s$ID$ = { 'densityIn' : densityIn_s$ID$, 'emission' : emission_s$ID$ }\n";
109 
110 const std::string smoke_alloc_noise =
111  "\n\
112 mantaMsg('Smoke alloc noise')\n\
113 vel_sn$ID$ = sn$ID$.create(MACGrid, name='$NAME_VELOCITY_NOISE$')\n\
114 density_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_DENSITY_NOISE$', sparse=True)\n\
115 phiIn_sn$ID$ = sn$ID$.create(LevelsetGrid, name='$NAME_PHIIN_NOISE$')\n\
116 phiOut_sn$ID$ = sn$ID$.create(LevelsetGrid, name='$NAME_PHIOUT_NOISE$')\n\
117 phiObs_sn$ID$ = sn$ID$.create(LevelsetGrid, name='$NAME_PHIOBS_NOISE$')\n\
118 flags_sn$ID$ = sn$ID$.create(FlagGrid, name='$NAME_FLAGS_NOISE$')\n\
119 tmpIn_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_TMPIN_NOISE$')\n\
120 emissionIn_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_EMISSIONIN_NOISE$')\n\
121 energy_s$ID$ = s$ID$.create(RealGrid, name='$NAME_ENERGY$')\n\
122 tmpFlags_s$ID$ = s$ID$.create(FlagGrid, name='$NAME_TMPFLAGS$')\n\
123 texture_u_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_U$')\n\
124 texture_v_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_V$')\n\
125 texture_w_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_W$')\n\
126 texture_u2_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_U2$')\n\
127 texture_v2_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_V2$')\n\
128 texture_w2_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_W2$')\n\
129 flame_sn$ID$ = None\n\
130 fuel_sn$ID$ = None\n\
131 react_sn$ID$ = None\n\
132 color_r_sn$ID$ = None\n\
133 color_g_sn$ID$ = None\n\
134 color_b_sn$ID$ = None\n\
135 wltnoise_sn$ID$ = sn$ID$.create(NoiseField, fixedSeed=265, loadFromFile=True)\n\
136 \n\
137 mantaMsg('Initializing UV Grids')\n\
138 uvGrid0_s$ID$ = s$ID$.create(VecGrid, name='$NAME_UV0$', sparse=False)\n\
139 uvGrid1_s$ID$ = s$ID$.create(VecGrid, name='$NAME_UV1$', sparse=False)\n\
140 resetUvGrid(target=uvGrid0_s$ID$, offset=uvs_offset_s$ID$)\n\
141 resetUvGrid(target=uvGrid1_s$ID$, offset=uvs_offset_s$ID$)\n\
142 \n\
143 # Sync UV and texture grids\n\
144 copyVec3ToReal(source=uvGrid0_s$ID$, targetX=texture_u_s$ID$, targetY=texture_v_s$ID$, targetZ=texture_w_s$ID$)\n\
145 copyVec3ToReal(source=uvGrid1_s$ID$, targetX=texture_u2_s$ID$, targetY=texture_v2_s$ID$, targetZ=texture_w2_s$ID$)\n\
146 \n\
147 # Keep track of important objects in dict to load them later on\n\
148 smoke_noise_dict_final_s$ID$ = { 'density_noise' : density_sn$ID$ }\n\
149 smoke_noise_dict_resume_s$ID$ = { 'uv0_noise' : uvGrid0_s$ID$, 'uv1_noise' : uvGrid1_s$ID$ }\n";
150 
152 // ADDITIONAL GRIDS
154 
155 const std::string smoke_alloc_colors =
156  "\n\
157 # Sanity check, clear grids first\n\
158 if 'color_r_s$ID$' in globals(): del color_r_s$ID$\n\
159 if 'color_g_s$ID$' in globals(): del color_g_s$ID$\n\
160 if 'color_b_s$ID$' in globals(): del color_b_s$ID$\n\
161 \n\
162 mantaMsg('Allocating colors')\n\
163 color_r_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORR$', sparse=True)\n\
164 color_g_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORG$', sparse=True)\n\
165 color_b_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORB$', sparse=True)\n\
166 color_r_in_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORRIN$', sparse=True)\n\
167 color_g_in_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORGIN$', sparse=True)\n\
168 color_b_in_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORBIN$', sparse=True)\n\
169 \n\
170 # Add objects to dict to load them later on\n\
171 if 'smoke_data_dict_final_s$ID$' in globals():\n\
172  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\
173 if 'smoke_data_dict_resume_s$ID$' in globals():\n\
174  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";
175 
176 const std::string smoke_alloc_colors_noise =
177  "\n\
178 # Sanity check, clear grids first\n\
179 if 'color_r_sn$ID$' in globals(): del color_r_sn$ID$\n\
180 if 'color_g_sn$ID$' in globals(): del color_g_sn$ID$\n\
181 if 'color_b_sn$ID$' in globals(): del color_b_sn$ID$\n\
182 \n\
183 mantaMsg('Allocating colors noise')\n\
184 color_r_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORR_NOISE$', sparse=True)\n\
185 color_g_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORG_NOISE$', sparse=True)\n\
186 color_b_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORB_NOISE$', sparse=True)\n\
187 \n\
188 # Add objects to dict to load them later on\n\
189 if 'smoke_noise_dict_final_s$ID$' in globals():\n\
190  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";
191 
192 const std::string smoke_init_colors =
193  "\n\
194 mantaMsg('Initializing colors')\n\
195 color_r_s$ID$.copyFrom(density_s$ID$) \n\
196 color_r_s$ID$.multConst($COLOR_R$) \n\
197 color_g_s$ID$.copyFrom(density_s$ID$) \n\
198 color_g_s$ID$.multConst($COLOR_G$) \n\
199 color_b_s$ID$.copyFrom(density_s$ID$) \n\
200 color_b_s$ID$.multConst($COLOR_B$)\n";
201 
202 const std::string smoke_init_colors_noise =
203  "\n\
204 mantaMsg('Initializing colors noise')\n\
205 color_r_sn$ID$.copyFrom(density_sn$ID$) \n\
206 color_r_sn$ID$.multConst($COLOR_R$) \n\
207 color_g_sn$ID$.copyFrom(density_sn$ID$) \n\
208 color_g_sn$ID$.multConst($COLOR_G$) \n\
209 color_b_sn$ID$.copyFrom(density_sn$ID$) \n\
210 color_b_sn$ID$.multConst($COLOR_B$)\n";
211 
212 const std::string smoke_alloc_heat =
213  "\n\
214 # Sanity check, clear grids first\n\
215 if 'heat_s$ID$' in globals(): del heat_s$ID$\n\
216 if 'heatIn_s$ID$' in globals(): del heatIn_s$ID$\n\
217 \n\
218 mantaMsg('Allocating heat')\n\
219 heat_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEMPERATURE$', sparse=True)\n\
220 heatIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEMPERATUREIN$', sparse=True)\n\
221 \n\
222 # Add objects to dict to load them later on\n\
223 if 'smoke_data_dict_final_s$ID$' in globals():\n\
224  smoke_data_dict_final_s$ID$.update(heat=heat_s$ID$)\n\
225 if 'smoke_data_dict_resume_s$ID$' in globals():\n\
226  smoke_data_dict_resume_s$ID$.update(heatIn=heatIn_s$ID$)\n";
227 
228 const std::string smoke_alloc_fire =
229  "\n\
230 # Sanity check, clear grids first\n\
231 if 'flame_s$ID$' in globals(): del flame_s$ID$\n\
232 if 'fuel_s$ID$' in globals(): del fuel_s$ID$\n\
233 if 'react_s$ID$' in globals(): del react_s$ID$\n\
234 if 'fuelIn_s$ID$' in globals(): del fuelIn_s$ID$\n\
235 if 'reactIn_s$ID$' in globals(): del reactIn_s$ID$\n\
236 \n\
237 mantaMsg('Allocating fire')\n\
238 flame_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FLAME$', sparse=True)\n\
239 fuel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FUEL$', sparse=True)\n\
240 react_s$ID$ = s$ID$.create(RealGrid, name='$NAME_REACT$', sparse=True)\n\
241 fuelIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FUELIN$', sparse=True)\n\
242 reactIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_REACTIN$', sparse=True)\n\
243 \n\
244 # Add objects to dict to load them later on\n\
245 if 'smoke_data_dict_final_s$ID$' in globals():\n\
246  smoke_data_dict_final_s$ID$.update(flame=flame_s$ID$)\n\
247 if 'smoke_data_dict_resume_s$ID$' in globals():\n\
248  smoke_data_dict_resume_s$ID$.update(fuel=fuel_s$ID$, react=react_s$ID$, fuelIn=fuelIn_s$ID$, reactIn=reactIn_s$ID$)\n";
249 
250 const std::string smoke_alloc_fire_noise =
251  "\n\
252 # Sanity check, clear grids first\n\
253 if 'flame_sn$ID$' in globals(): del flame_sn$ID$\n\
254 if 'fuel_sn$ID$' in globals(): del fuel_sn$ID$\n\
255 if 'react_sn$ID$' in globals(): del react_sn$ID$\n\
256 \n\
257 mantaMsg('Allocating fire noise')\n\
258 flame_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_FLAME_NOISE$', sparse=True)\n\
259 fuel_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_FUEL_NOISE$', sparse=True)\n\
260 react_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_REACT_NOISE$', sparse=True)\n\
261 \n\
262 # Add objects to dict to load them later on\n\
263 if 'smoke_noise_dict_final_s$ID$' in globals():\n\
264  smoke_noise_dict_final_s$ID$.update(flame_noise=flame_sn$ID$)\n\
265 if 'smoke_noise_dict_resume_s$ID$' in globals():\n\
266  smoke_noise_dict_resume_s$ID$.update(fuel_noise=fuel_sn$ID$, react_noise=react_sn$ID$)\n";
267 
269 // STEP FUNCTIONS
271 
272 const std::string smoke_adaptive_step =
273  "\n\
274 def smoke_adaptive_step_$ID$(framenr):\n\
275  mantaMsg('Manta step, frame ' + str(framenr))\n\
276  s$ID$.frame = framenr\n\
277  \n\
278  fluid_pre_step_$ID$()\n\
279  \n\
280  flags_s$ID$.initDomain(boundaryWidth=0, phiWalls=phiObs_s$ID$, outflow=boundConditions_s$ID$)\n\
281  \n\
282  if using_obstacle_s$ID$:\n\
283  mantaMsg('Extrapolating object velocity')\n\
284  # ensure velocities inside of obs object, slightly add obvels outside of obs object\n\
285  # extrapolate with phiObsIn before joining (static) phiObsSIn grid to prevent flows into static obs\n\
286  extrapolateVec3Simple(vel=obvelC_s$ID$, phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
287  extrapolateVec3Simple(vel=obvelC_s$ID$, phi=phiObsIn_s$ID$, distance=3, inside=False)\n\
288  resampleVec3ToMac(source=obvelC_s$ID$, target=obvel_s$ID$)\n\
289  \n\
290  mantaMsg('Initializing obstacle levelset')\n\
291  phiObsIn_s$ID$.join(phiObsSIn_s$ID$) # Join static obstacle map\n\
292  phiObsIn_s$ID$.floodFill(boundaryWidth=1)\n\
293  extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
294  extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=3, inside=False)\n\
295  phiObs_s$ID$.join(phiObsIn_s$ID$)\n\
296  \n\
297  # Additional sanity check: fill holes in phiObs which can result after joining with phiObsIn\n\
298  phiObs_s$ID$.floodFill(boundaryWidth=1)\n\
299  extrapolateLsSimple(phi=phiObs_s$ID$, distance=6, inside=True)\n\
300  extrapolateLsSimple(phi=phiObs_s$ID$, distance=3, inside=False)\n\
301  \n\
302  mantaMsg('Initializing fluid levelset')\n\
303  phiIn_s$ID$.join(phiSIn_s$ID$) # Join static flow map\n\
304  extrapolateLsSimple(phi=phiIn_s$ID$, distance=6, inside=True)\n\
305  extrapolateLsSimple(phi=phiIn_s$ID$, distance=3, inside=False)\n\
306  \n\
307  if using_outflow_s$ID$:\n\
308  phiOutIn_s$ID$.join(phiOutSIn_s$ID$) # Join static outflow map\n\
309  phiOut_s$ID$.join(phiOutIn_s$ID$)\n\
310  \n\
311  setObstacleFlags(flags=flags_s$ID$, phiObs=phiObs_s$ID$, phiOut=phiOut_s$ID$, phiIn=phiIn_s$ID$, boundaryWidth=1)\n\
312  flags_s$ID$.fillGrid()\n\
313  \n\
314  # reset emission accumulation at the beginning of an adaptive frame\n\
315  if not s$ID$.timePerFrame:\n\
316  emission_s$ID$.setConst(0.)\n\
317  # accumulate emission value per adaptive step for later use in noise computation\n\
318  emission_s$ID$.join(emissionIn_s$ID$)\n\
319  \n\
320  applyEmission(flags=flags_s$ID$, target=density_s$ID$, source=densityIn_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
321  if using_heat_s$ID$:\n\
322  applyEmission(flags=flags_s$ID$, target=heat_s$ID$, source=heatIn_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
323  \n\
324  if using_colors_s$ID$:\n\
325  applyEmission(flags=flags_s$ID$, target=color_r_s$ID$, source=color_r_in_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
326  applyEmission(flags=flags_s$ID$, target=color_g_s$ID$, source=color_g_in_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
327  applyEmission(flags=flags_s$ID$, target=color_b_s$ID$, source=color_b_in_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
328  \n\
329  if using_fire_s$ID$:\n\
330  applyEmission(flags=flags_s$ID$, target=fuel_s$ID$, source=fuelIn_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
331  applyEmission(flags=flags_s$ID$, target=react_s$ID$, source=reactIn_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
332  \n\
333  mantaMsg('Smoke step / s$ID$.frame: ' + str(s$ID$.frame))\n\
334  if using_fire_s$ID$:\n\
335  process_burn_$ID$()\n\
336  smoke_step_$ID$()\n\
337  if using_fire_s$ID$:\n\
338  update_flame_$ID$()\n\
339  \n\
340  s$ID$.step()\n\
341  \n\
342  fluid_post_step_$ID$()\n";
343 
344 const std::string smoke_step =
345  "\n\
346 def smoke_step_$ID$():\n\
347  mantaMsg('Smoke step low')\n\
348  \n\
349  # save original state for later (used during noise creation)\n\
350  velTmp_s$ID$.copyFrom(vel_s$ID$)\n\
351  \n\
352  if using_dissolve_s$ID$:\n\
353  mantaMsg('Dissolving smoke')\n\
354  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$)\n\
355  \n\
356  mantaMsg('Advecting density')\n\
357  advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=density_s$ID$, order=2)\n\
358  \n\
359  if using_heat_s$ID$:\n\
360  mantaMsg('Advecting heat')\n\
361  advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=heat_s$ID$, order=2)\n\
362  \n\
363  if using_fire_s$ID$:\n\
364  mantaMsg('Advecting fire')\n\
365  advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=fuel_s$ID$, order=2)\n\
366  advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=react_s$ID$, order=2)\n\
367  \n\
368  if using_colors_s$ID$:\n\
369  mantaMsg('Advecting colors')\n\
370  advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=color_r_s$ID$, order=2)\n\
371  advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=color_g_s$ID$, order=2)\n\
372  advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=color_b_s$ID$, order=2)\n\
373  \n\
374  mantaMsg('Advecting velocity')\n\
375  advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=vel_s$ID$, order=2)\n\
376  \n\
377  if not domainClosed_s$ID$ or using_outflow_s$ID$:\n\
378  resetOutflow(flags=flags_s$ID$, real=density_s$ID$)\n\
379  \n\
380  mantaMsg('Vorticity')\n\
381  if using_fire_s$ID$:\n\
382  flame_s$ID$.copyFrom(fuel_s$ID$) # temporarily misuse flame grid as vorticity storage\n\
383  flame_s$ID$.multConst(flameVorticity_s$ID$)\n\
384  vorticityConfinement(vel=vel_s$ID$, flags=flags_s$ID$, strength=vorticity_s$ID$, strengthCell=flame_s$ID$ if using_fire_s$ID$ else None)\n\
385  \n\
386  if using_heat_s$ID$:\n\
387  mantaMsg('Adding heat buoyancy')\n\
388  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\
389  mantaMsg('Adding buoyancy')\n\
390  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\
391  \n\
392  mantaMsg('Adding forces')\n\
393  addForceField(flags=flags_s$ID$, vel=vel_s$ID$, force=forces_s$ID$)\n\
394  \n\
395  # Cells inside obstacle should not contain any density, fire, etc.\n\
396  if deleteInObstacle_s$ID$:\n\
397  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\
398  \n\
399  # add initial velocity\n\
400  if using_invel_s$ID$:\n\
401  # Using cell centered invels, will be converted to MAC within the function\n\
402  setInitialVelocity(flags=flags_s$ID$, vel=vel_s$ID$, invel=invelC_s$ID$)\n\
403  \n\
404  mantaMsg('Walls')\n\
405  setWallBcs(flags=flags_s$ID$, vel=vel_s$ID$, obvel=obvel_s$ID$ if using_obstacle_s$ID$ else None)\n\
406  \n\
407  preconditioner_s$ID$ = PcMGDynamic if using_obstacle_s$ID$ and obvel_s$ID$.getMax() > 0 else PcMGStatic\n\
408  mantaMsg('Using preconditioner: ' + str(preconditioner_s$ID$))\n\
409  if using_guiding_s$ID$:\n\
410  mantaMsg('Guiding and pressure')\n\
411  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\
412  else:\n\
413  mantaMsg('Pressure')\n\
414  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\
415 \n\
416 def process_burn_$ID$():\n\
417  mantaMsg('Process burn')\n\
418  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\
419 \n\
420 def update_flame_$ID$():\n\
421  mantaMsg('Update flame')\n\
422  updateFlame(react=react_s$ID$, flame=flame_s$ID$)\n";
423 
424 const std::string smoke_step_noise =
425  "\n\
426 def smoke_step_noise_$ID$(framenr):\n\
427  mantaMsg('Manta step noise, frame ' + str(framenr))\n\
428  sn$ID$.frame = framenr\n\
429  \n\
430  copyRealToVec3(sourceX=texture_u_s$ID$, sourceY=texture_v_s$ID$, sourceZ=texture_w_s$ID$, target=uvGrid0_s$ID$)\n\
431  copyRealToVec3(sourceX=texture_u2_s$ID$, sourceY=texture_v2_s$ID$, sourceZ=texture_w2_s$ID$, target=uvGrid1_s$ID$)\n\
432  \n\
433  flags_sn$ID$.initDomain(boundaryWidth=0, phiWalls=phiObs_sn$ID$, outflow=boundConditions_s$ID$)\n\
434  \n\
435  mantaMsg('Interpolating grids')\n\
436  # Join big obstacle levelset after initDomain() call as it overwrites everything in phiObs\n\
437  if using_obstacle_s$ID$:\n\
438  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\
439  phiObs_sn$ID$.join(phiIn_sn$ID$)\n\
440  if using_outflow_s$ID$:\n\
441  phiOut_sn$ID$.copyFrom(phiOut_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(target=phiOut_sn$ID$, source=phiOut_s$ID$)\n\
442  phiIn_sn$ID$.copyFrom(phiIn_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(target=phiIn_sn$ID$, source=phiIn_s$ID$)\n\
443  vel_sn$ID$.copyFrom(velTmp_s$ID$) if upres_sn$ID$ <= 1 else interpolateMACGrid(target=vel_sn$ID$, source=velTmp_s$ID$)\n\
444  \n\
445  setObstacleFlags(flags=flags_sn$ID$, phiObs=phiObs_sn$ID$, phiOut=phiOut_sn$ID$, phiIn=phiIn_sn$ID$, boundaryWidth=1)\n\
446  flags_sn$ID$.fillGrid()\n\
447  \n\
448  # Interpolate emission grids and apply them to big noise grids\n\
449  tmpIn_sn$ID$.copyFrom(densityIn_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=densityIn_s$ID$, target=tmpIn_sn$ID$)\n\
450  emissionIn_sn$ID$.copyFrom(emission_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=emission_s$ID$, target=emissionIn_sn$ID$)\n\
451  \n\
452  # Higher-res noise grid needs scaled emission values\n\
453  tmpIn_sn$ID$.multConst(float(upres_sn$ID$))\n\
454  applyEmission(flags=flags_sn$ID$, target=density_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
455  \n\
456  if using_colors_s$ID$:\n\
457  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\
458  applyEmission(flags=flags_sn$ID$, target=color_r_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
459  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\
460  applyEmission(flags=flags_sn$ID$, target=color_g_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
461  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\
462  applyEmission(flags=flags_sn$ID$, target=color_b_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
463  \n\
464  if using_fire_s$ID$:\n\
465  tmpIn_sn$ID$.copyFrom(fuelIn_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=fuelIn_s$ID$, target=tmpIn_sn$ID$)\n\
466  applyEmission(flags=flags_sn$ID$, target=fuel_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
467  tmpIn_sn$ID$.copyFrom(reactIn_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=reactIn_s$ID$, target=tmpIn_sn$ID$)\n\
468  applyEmission(flags=flags_sn$ID$, target=react_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
469  \n\
470  mantaMsg('Noise step / sn$ID$.frame: ' + str(sn$ID$.frame))\n\
471  if using_fire_s$ID$:\n\
472  process_burn_noise_$ID$()\n\
473  step_noise_$ID$()\n\
474  if using_fire_s$ID$:\n\
475  update_flame_noise_$ID$()\n\
476  \n\
477  sn$ID$.step()\n\
478  \n\
479  copyVec3ToReal(source=uvGrid0_s$ID$, targetX=texture_u_s$ID$, targetY=texture_v_s$ID$, targetZ=texture_w_s$ID$)\n\
480  copyVec3ToReal(source=uvGrid1_s$ID$, targetX=texture_u2_s$ID$, targetY=texture_v2_s$ID$, targetZ=texture_w2_s$ID$)\n\
481 \n\
482 def step_noise_$ID$():\n\
483  mantaMsg('Smoke step noise')\n\
484  \n\
485  if using_dissolve_s$ID$:\n\
486  mantaMsg('Dissolving noise')\n\
487  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$)\n\
488  \n\
489  mantaMsg('Advecting UVs and updating UV weight')\n\
490  advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=uvGrid0_s$ID$, order=2)\n\
491  updateUvWeight(resetTime=sn$ID$.timestep*10.0 , index=0, numUvs=uvs_s$ID$, uv=uvGrid0_s$ID$, offset=uvs_offset_s$ID$)\n\
492  advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=uvGrid1_s$ID$, order=2)\n\
493  updateUvWeight(resetTime=sn$ID$.timestep*10.0 , index=1, numUvs=uvs_s$ID$, uv=uvGrid1_s$ID$, offset=uvs_offset_s$ID$)\n\
494  \n\
495  if not domainClosed_s$ID$ or using_outflow_s$ID$:\n\
496  resetOutflow(flags=flags_sn$ID$, real=density_sn$ID$)\n\
497  \n\
498  mantaMsg('Energy')\n\
499  computeEnergy(flags=flags_s$ID$, vel=vel_s$ID$, energy=energy_s$ID$)\n\
500  \n\
501  tmpFlags_s$ID$.copyFrom(flags_s$ID$)\n\
502  extrapolateSimpleFlags(flags=flags_s$ID$, val=tmpFlags_s$ID$, distance=2, flagFrom=FlagObstacle, flagTo=FlagFluid)\n\
503  extrapolateSimpleFlags(flags=tmpFlags_s$ID$, val=energy_s$ID$, distance=6, flagFrom=FlagFluid, flagTo=FlagObstacle)\n\
504  computeWaveletCoeffs(energy_s$ID$)\n\
505  \n\
506  sStr_s$ID$ = 1.0 * wltStrength_s$ID$\n\
507  sPos_s$ID$ = 2.0\n\
508  \n\
509  mantaMsg('Applying noise vec')\n\
510  for o in range(octaves_s$ID$):\n\
511  uvWeight_s$ID$ = getUvWeight(uvGrid0_s$ID$)\n\
512  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\
513  uvWeight_s$ID$ = getUvWeight(uvGrid1_s$ID$)\n\
514  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\
515  \n\
516  sStr_s$ID$ *= 0.06 # magic kolmogorov factor \n\
517  sPos_s$ID$ *= 2.0 \n\
518  \n\
519  for substep in range(int(upres_sn$ID$)):\n\
520  if using_colors_s$ID$: \n\
521  mantaMsg('Advecting colors noise')\n\
522  advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=color_r_sn$ID$, order=2)\n\
523  advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=color_g_sn$ID$, order=2)\n\
524  advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=color_b_sn$ID$, order=2)\n\
525  \n\
526  if using_fire_s$ID$: \n\
527  mantaMsg('Advecting fire noise')\n\
528  advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=fuel_sn$ID$, order=2)\n\
529  advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=react_sn$ID$, order=2)\n\
530  \n\
531  mantaMsg('Advecting density noise')\n\
532  advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=density_sn$ID$, order=2)\n\
533 \n\
534 def process_burn_noise_$ID$():\n\
535  mantaMsg('Process burn noise')\n\
536  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\
537 \n\
538 def update_flame_noise_$ID$():\n\
539  mantaMsg('Update flame noise')\n\
540  updateFlame(react=react_sn$ID$, flame=flame_sn$ID$)\n";
541 
543 // IMPORT
545 
546 const std::string smoke_load_data =
547  "\n\
548 def smoke_load_data_$ID$(path, framenr, file_format, resumable):\n\
549  mantaMsg('Smoke load data')\n\
550  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\
551  fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$)\n\
552  \n\
553  copyVec3ToReal(source=vel_s$ID$, targetX=x_vel_s$ID$, targetY=y_vel_s$ID$, targetZ=z_vel_s$ID$)\n";
554 
555 const std::string smoke_load_noise =
556  "\n\
557 def smoke_load_noise_$ID$(path, framenr, file_format, resumable):\n\
558  mantaMsg('Smoke load noise')\n\
559  dict = { **smoke_noise_dict_final_s$ID$, **smoke_noise_dict_resume_s$ID$ } if resumable else { **smoke_noise_dict_final_s$ID$ } \n\
560  fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_noise_s$ID$)\n\
561  \n\
562  if resumable:\n\
563  # Fill up xyz texture grids, important when resuming a bake\n\
564  copyVec3ToReal(source=uvGrid0_s$ID$, targetX=texture_u_s$ID$, targetY=texture_v_s$ID$, targetZ=texture_w_s$ID$)\n\
565  copyVec3ToReal(source=uvGrid1_s$ID$, targetX=texture_u2_s$ID$, targetY=texture_v2_s$ID$, targetZ=texture_w2_s$ID$)\n";
566 
568 // EXPORT
570 
571 const std::string smoke_save_data =
572  "\n\
573 def smoke_save_data_$ID$(path, framenr, file_format, resumable):\n\
574  mantaMsg('Smoke save data')\n\
575  start_time = time.time()\n\
576  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\
577  if not withMPSave or isWindows:\n\
578  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\
579  else:\n\
580  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\
581  mantaMsg('--- Save: %s seconds ---' % (time.time() - start_time))\n";
582 
583 const std::string smoke_save_noise =
584  "\n\
585 def smoke_save_noise_$ID$(path, framenr, file_format, resumable):\n\
586  mantaMsg('Smoke save noise')\n\
587  dict = { **smoke_noise_dict_final_s$ID$, **smoke_noise_dict_resume_s$ID$ } if resumable else { **smoke_noise_dict_final_s$ID$ } \n\
588  if not withMPSave or isWindows:\n\
589  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\
590  else:\n\
591  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";
592 
594 // STANDALONE MODE
596 
597 const std::string smoke_standalone =
598  "\n\
599 # Helper function to call cache load functions\n\
600 def load_data(frame, cache_resumable):\n\
601  smoke_load_data_$ID$(os.path.join(cache_dir, 'data'), frame, file_format_data, cache_resumable)\n\
602  if using_noise_s$ID$:\n\
603  smoke_load_noise_$ID$(os.path.join(cache_dir, 'noise'), frame, file_format_data, cache_resumable)\n\
604  if using_guiding_s$ID$:\n\
605  fluid_load_guiding_$ID$(os.path.join(cache_dir, 'guiding'), frame, file_format_data)\n\
606 \n\
607 # Helper function to call step functions\n\
608 def step(frame):\n\
609  smoke_adaptive_step_$ID$(frame)\n\
610  if using_noise_s$ID$:\n\
611  smoke_step_noise_$ID$(frame)\n";
const std::string smoke_alloc_noise
Definition: smoke_script.h:110
const std::string smoke_alloc_heat
Definition: smoke_script.h:212
const std::string smoke_alloc_colors
Definition: smoke_script.h:155
const std::string smoke_alloc_fire_noise
Definition: smoke_script.h:250
const std::string smoke_save_noise
Definition: smoke_script.h:583
const std::string smoke_adaptive_step
Definition: smoke_script.h:272
const std::string smoke_standalone
Definition: smoke_script.h:597
const std::string smoke_with_colors
Definition: smoke_script.h:69
const std::string smoke_load_data
Definition: smoke_script.h:546
const std::string smoke_with_fire
Definition: smoke_script.h:73
const std::string smoke_with_heat
Definition: smoke_script.h:65
const std::string smoke_variables
Definition: smoke_script.h:30
const std::string smoke_variables_noise
Definition: smoke_script.h:51
const std::string smoke_save_data
Definition: smoke_script.h:571
const std::string smoke_alloc_colors_noise
Definition: smoke_script.h:176
const std::string smoke_load_noise
Definition: smoke_script.h:555
const std::string smoke_init_colors_noise
Definition: smoke_script.h:202
const std::string smoke_step_noise
Definition: smoke_script.h:424
const std::string smoke_init_colors
Definition: smoke_script.h:192
const std::string smoke_wavelet_noise
Definition: smoke_script.h:59
const std::string smoke_alloc_fire
Definition: smoke_script.h:228
const std::string smoke_alloc
Definition: smoke_script.h:81
const std::string smoke_step
Definition: smoke_script.h:344