Blender  V2.93
liquid_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 liquid_variables =
31  "\n\
32 mantaMsg('Liquid variables')\n\
33 narrowBandWidth_s$ID$ = 3\n\
34 combineBandWidth_s$ID$ = narrowBandWidth_s$ID$ - 1\n\
35 adjustedNarrowBandWidth_s$ID$ = $PARTICLE_BAND_WIDTH$ # only used in adjustNumber to control band width\n\
36 particleNumber_s$ID$ = $PARTICLE_NUMBER$\n\
37 minParticles_s$ID$ = $PARTICLE_MINIMUM$\n\
38 maxParticles_s$ID$ = $PARTICLE_MAXIMUM$\n\
39 radiusFactor_s$ID$ = $PARTICLE_RADIUS$\n\
40 using_mesh_s$ID$ = $USING_MESH$\n\
41 using_final_mesh_s$ID$ = $USING_IMPROVED_MESH$\n\
42 using_fractions_s$ID$ = $USING_FRACTIONS$\n\
43 using_apic_s$ID$ = $USING_APIC$\n\
44 using_viscosity_s$ID$ = $USING_VISCOSITY$\n\
45 fracThreshold_s$ID$ = $FRACTIONS_THRESHOLD$\n\
46 fracDistance_s$ID$ = $FRACTIONS_DISTANCE$\n\
47 flipRatio_s$ID$ = $FLIP_RATIO$\n\
48 concaveUpper_s$ID$ = $MESH_CONCAVE_UPPER$\n\
49 concaveLower_s$ID$ = $MESH_CONCAVE_LOWER$\n\
50 meshRadiusFactor_s$ID$ = $MESH_PARTICLE_RADIUS$\n\
51 smoothenPos_s$ID$ = $MESH_SMOOTHEN_POS$\n\
52 smoothenNeg_s$ID$ = $MESH_SMOOTHEN_NEG$\n\
53 randomness_s$ID$ = $PARTICLE_RANDOMNESS$\n\
54 surfaceTension_s$ID$ = $LIQUID_SURFACE_TENSION$\n\
55 maxSysParticles_s$ID$ = $PP_PARTICLE_MAXIMUM$\n\
56 viscosityValue_s$ID$ = $VISCOSITY_VALUE$\n";
57 
58 const std::string liquid_variables_particles =
59  "\n\
60 tauMin_wc_sp$ID$ = $SNDPARTICLE_TAU_MIN_WC$\n\
61 tauMax_wc_sp$ID$ = $SNDPARTICLE_TAU_MAX_WC$\n\
62 tauMin_ta_sp$ID$ = $SNDPARTICLE_TAU_MIN_TA$\n\
63 tauMax_ta_sp$ID$ = $SNDPARTICLE_TAU_MAX_TA$\n\
64 tauMin_k_sp$ID$ = $SNDPARTICLE_TAU_MIN_K$\n\
65 tauMax_k_sp$ID$ = $SNDPARTICLE_TAU_MAX_K$\n\
66 k_wc_sp$ID$ = $SNDPARTICLE_K_WC$\n\
67 k_ta_sp$ID$ = $SNDPARTICLE_K_TA$\n\
68 k_b_sp$ID$ = $SNDPARTICLE_K_B$\n\
69 k_d_sp$ID$ = $SNDPARTICLE_K_D$\n\
70 lMin_sp$ID$ = $SNDPARTICLE_L_MIN$\n\
71 lMax_sp$ID$ = $SNDPARTICLE_L_MAX$\n\
72 c_s_sp$ID$ = 0.4 # classification constant for snd parts\n\
73 c_b_sp$ID$ = 0.77 # classification constant for snd parts\n\
74 pot_radius_sp$ID$ = $SNDPARTICLE_POTENTIAL_RADIUS$\n\
75 update_radius_sp$ID$ = $SNDPARTICLE_UPDATE_RADIUS$\n\
76 using_snd_pushout_sp$ID$ = $SNDPARTICLE_BOUNDARY_PUSHOUT$\n";
77 
79 // GRIDS & MESH & PARTICLESYSTEM
81 
82 const std::string liquid_alloc =
83  "\n\
84 mantaMsg('Liquid alloc')\n\
85 phiParts_s$ID$ = s$ID$.create(LevelsetGrid, name='$NAME_PHIPARTS$')\n\
86 phi_s$ID$ = s$ID$.create(LevelsetGrid, name='$NAME_PHI$')\n\
87 phiTmp_s$ID$ = s$ID$.create(LevelsetGrid, name='$NAME_PHITMP$')\n\
88 velOld_s$ID$ = s$ID$.create(MACGrid, name='$NAME_VELOLD$')\n\
89 velParts_s$ID$ = s$ID$.create(MACGrid, name='$NAME_VELPARTS$')\n\
90 mapWeights_s$ID$ = s$ID$.create(MACGrid, name='$NAME_MAPWEIGHTS$')\n\
91 fractions_s$ID$ = None # allocated dynamically\n\
92 curvature_s$ID$ = None\n\
93 \n\
94 pp_s$ID$ = s$ID$.create(BasicParticleSystem, name='$NAME_PARTS$')\n\
95 pVel_pp$ID$ = pp_s$ID$.create(PdataVec3, name='$NAME_PARTSVELOCITY$')\n\
96 \n\
97 pCx_pp$ID$ = None\n\
98 pCy_pp$ID$ = None\n\
99 pCz_pp$ID$ = None\n\
100 if using_apic_s$ID$:\n\
101  pCx_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\
102  pCy_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\
103  pCz_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\
104 \n\
105 # Acceleration data for particle nbs\n\
106 pindex_s$ID$ = s$ID$.create(ParticleIndexSystem, name='$NAME_PINDEX$')\n\
107 gpi_s$ID$ = s$ID$.create(IntGrid, name='$NAME_GPI$')\n\
108 \n\
109 # Keep track of important objects in dict to load them later on\n\
110 liquid_data_dict_final_s$ID$ = { 'pVel' : pVel_pp$ID$, 'pp' : pp_s$ID$ }\n\
111 liquid_data_dict_resume_s$ID$ = { 'phiParts' : phiParts_s$ID$, 'phi' : phi_s$ID$, 'phiTmp' : phiTmp_s$ID$ }\n";
112 
113 const std::string liquid_alloc_mesh =
114  "\n\
115 mantaMsg('Liquid alloc mesh')\n\
116 phiParts_sm$ID$ = sm$ID$.create(LevelsetGrid, name='$NAME_PHIPARTS_MESH$')\n\
117 phi_sm$ID$ = sm$ID$.create(LevelsetGrid, name='$NAME_PHI_MESH$')\n\
118 pp_sm$ID$ = sm$ID$.create(BasicParticleSystem, name='$NAME_PP_MESH$')\n\
119 flags_sm$ID$ = sm$ID$.create(FlagGrid, name='$NAME_FLAGS_MESH$')\n\
120 mesh_sm$ID$ = sm$ID$.create(Mesh, name='$NAME_MESH$')\n\
121 \n\
122 if using_speedvectors_s$ID$:\n\
123  mVel_mesh$ID$ = mesh_sm$ID$.create(MdataVec3, name='$NAME_VELOCITYVEC_MESH$')\n\
124  vel_sm$ID$ = sm$ID$.create(MACGrid, name='$NAME_VELOCITY_MESH$')\n\
125 \n\
126 # Acceleration data for particle nbs\n\
127 pindex_sm$ID$ = sm$ID$.create(ParticleIndexSystem, name='$NAME_PINDEX_MESH$')\n\
128 gpi_sm$ID$ = sm$ID$.create(IntGrid, name='$NAME_GPI_MESH$')\n\
129 \n\
130 # Set some initial values\n\
131 phiParts_sm$ID$.setConst(9999)\n\
132 phi_sm$ID$.setConst(9999)\n\
133 \n\
134 # Keep track of important objects in dict to load them later on\n\
135 liquid_mesh_dict_s$ID$ = { 'lMesh' : mesh_sm$ID$ }\n\
136 \n\
137 if using_speedvectors_s$ID$:\n\
138  liquid_meshvel_dict_s$ID$ = { 'lVelMesh' : mVel_mesh$ID$ }\n";
139 
140 const std::string liquid_alloc_viscosity =
141  "\n\
142 # Viscosity grids\n\
143 volumes_s$ID$ = sv$ID$.create(RealGrid)\n\
144 viscosity_s$ID$ = s$ID$.create(RealGrid)\n\
145 viscosity_s$ID$.setConst(viscosityValue_s$ID$)\n";
146 
147 const std::string liquid_alloc_curvature =
148  "\n\
149 mantaMsg('Liquid alloc curvature')\n\
150 curvature_s$ID$ = s$ID$.create(RealGrid, name='$NAME_CURVATURE$')\n";
151 
152 const std::string liquid_alloc_particles =
153  "\n\
154 ppSnd_sp$ID$ = sp$ID$.create(BasicParticleSystem, name='$NAME_PARTS_PARTICLES$')\n\
155 pVelSnd_pp$ID$ = ppSnd_sp$ID$.create(PdataVec3, name='$NAME_PARTSVEL_PARTICLES$')\n\
156 pForceSnd_pp$ID$ = ppSnd_sp$ID$.create(PdataVec3, name='$NAME_PARTSFORCE_PARTICLES$')\n\
157 pLifeSnd_pp$ID$ = ppSnd_sp$ID$.create(PdataReal, name='$NAME_PARTSLIFE_PARTICLES$')\n\
158 vel_sp$ID$ = sp$ID$.create(MACGrid, name='$NAME_VELOCITY_PARTICLES$')\n\
159 flags_sp$ID$ = sp$ID$.create(FlagGrid, name='$NAME_FLAGS_PARTICLES$')\n\
160 phi_sp$ID$ = sp$ID$.create(LevelsetGrid, name='$NAME_PHI_PARTICLES$')\n\
161 phiObs_sp$ID$ = sp$ID$.create(LevelsetGrid, name='$NAME_PHIOBS_PARTICLES$')\n\
162 phiOut_sp$ID$ = sp$ID$.create(LevelsetGrid, name='$NAME_PHIOUT_PARTICLES$')\n\
163 normal_sp$ID$ = sp$ID$.create(VecGrid, name='$NAME_NORMAL_PARTICLES$')\n\
164 neighborRatio_sp$ID$ = sp$ID$.create(RealGrid, name='$NAME_NEIGHBORRATIO_PARTICLES$')\n\
165 trappedAir_sp$ID$ = sp$ID$.create(RealGrid, name='$NAME_TRAPPEDAIR_PARTICLES$')\n\
166 waveCrest_sp$ID$ = sp$ID$.create(RealGrid, name='$NAME_WAVECREST_PARTICLES$')\n\
167 kineticEnergy_sp$ID$ = sp$ID$.create(RealGrid, name='$NAME_KINETICENERGY_PARTICLES$')\n\
168 \n\
169 # Set some initial values\n\
170 phi_sp$ID$.setConst(9999)\n\
171 phiObs_sp$ID$.setConst(9999)\n\
172 phiOut_sp$ID$.setConst(9999)\n\
173 \n\
174 # Keep track of important objects in dict to load them later on\n\
175 liquid_particles_dict_final_s$ID$ = { 'pVelSnd' : pVelSnd_pp$ID$, 'pLifeSnd' : pLifeSnd_pp$ID$, 'ppSnd' : ppSnd_sp$ID$ }\n\
176 liquid_particles_dict_resume_s$ID$ = { 'trappedAir' : trappedAir_sp$ID$, 'waveCrest' : waveCrest_sp$ID$, 'kineticEnergy' : kineticEnergy_sp$ID$ }\n";
177 
178 const std::string liquid_init_phi =
179  "\n\
180 # Prepare domain\n\
181 phi_s$ID$.initFromFlags(flags_s$ID$)\n\
182 phiIn_s$ID$.initFromFlags(flags_s$ID$)\n";
183 
185 // STEP FUNCTIONS
187 
188 const std::string liquid_adaptive_step =
189  "\n\
190 def liquid_adaptive_step_$ID$(framenr):\n\
191  mantaMsg('Manta step, frame ' + str(framenr))\n\
192  s$ID$.frame = framenr\n\
193  \n\
194  fluid_pre_step_$ID$()\n\
195  \n\
196  flags_s$ID$.initDomain(boundaryWidth=1 if using_fractions_s$ID$ else 0, phiWalls=phiObs_s$ID$, outflow=boundConditions_s$ID$)\n\
197  \n\
198  if using_obstacle_s$ID$:\n\
199  mantaMsg('Extrapolating object velocity')\n\
200  # ensure velocities inside of obs object, slightly add obvels outside of obs object\n\
201  # extrapolate with phiObsIn before joining (static) phiObsSIn grid to prevent flows into static obs\n\
202  extrapolateVec3Simple(vel=obvelC_s$ID$, phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
203  extrapolateVec3Simple(vel=obvelC_s$ID$, phi=phiObsIn_s$ID$, distance=3, inside=False)\n\
204  resampleVec3ToMac(source=obvelC_s$ID$, target=obvel_s$ID$)\n\
205  \n\
206  mantaMsg('Initializing obstacle levelset')\n\
207  phiObsIn_s$ID$.join(phiObsSIn_s$ID$) # Join static obstacle map\n\
208  phiObsIn_s$ID$.floodFill(boundaryWidth=1)\n\
209  extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
210  extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=3, inside=False)\n\
211  phiObs_s$ID$.join(phiObsIn_s$ID$)\n\
212  \n\
213  # Additional sanity check: fill holes in phiObs which can result after joining with phiObsIn\n\
214  phiObs_s$ID$.floodFill(boundaryWidth=2 if using_fractions_s$ID$ else 1)\n\
215  extrapolateLsSimple(phi=phiObs_s$ID$, distance=6, inside=True)\n\
216  extrapolateLsSimple(phi=phiObs_s$ID$, distance=3)\n\
217  \n\
218  mantaMsg('Initializing fluid levelset')\n\
219  phiIn_s$ID$.join(phiSIn_s$ID$) # Join static flow map\n\
220  extrapolateLsSimple(phi=phiIn_s$ID$, distance=6, inside=True)\n\
221  extrapolateLsSimple(phi=phiIn_s$ID$, distance=3)\n\
222  phi_s$ID$.join(phiIn_s$ID$)\n\
223  \n\
224  if using_outflow_s$ID$:\n\
225  phiOutIn_s$ID$.join(phiOutSIn_s$ID$) # Join static outflow map\n\
226  phiOut_s$ID$.join(phiOutIn_s$ID$)\n\
227  \n\
228  if using_fractions_s$ID$:\n\
229  updateFractions(flags=flags_s$ID$, phiObs=phiObs_s$ID$, fractions=fractions_s$ID$, boundaryWidth=boundaryWidth_s$ID$, fracThreshold=fracThreshold_s$ID$)\n\
230  setObstacleFlags(flags=flags_s$ID$, phiObs=phiObs_s$ID$, phiOut=phiOut_s$ID$, fractions=fractions_s$ID$, phiIn=phiIn_s$ID$)\n\
231  \n\
232  if using_obstacle_s$ID$:\n\
233  # TODO(sebbas): Enable flags check again, currently produces unstable particle behavior\n\
234  phi_s$ID$.subtract(o=phiObsIn_s$ID$) #, flags=flags_s$ID$, subtractType=FlagObstacle)\n\
235  \n\
236  # add initial velocity: set invel as source grid to ensure const vels in inflow region, sampling makes use of this\n\
237  if using_invel_s$ID$:\n\
238  extrapolateVec3Simple(vel=invelC_s$ID$, phi=phiIn_s$ID$, distance=6, inside=True)\n\
239  # Using cell centered invels, a false isMAC flag ensures correct interpolation\n\
240  pVel_pp$ID$.setSource(grid=invelC_s$ID$, isMAC=False)\n\
241  # reset pvel grid source before sampling new particles - ensures that new particles are initialized with 0 velocity\n\
242  else:\n\
243  pVel_pp$ID$.setSource(grid=None, isMAC=False)\n\
244  \n\
245  pp_s$ID$.maxParticles = maxSysParticles_s$ID$ # remember, 0 means no particle cap\n\
246  sampleLevelsetWithParticles(phi=phiIn_s$ID$, flags=flags_s$ID$, parts=pp_s$ID$, discretization=particleNumber_s$ID$, randomness=randomness_s$ID$)\n\
247  flags_s$ID$.updateFromLevelset(phi_s$ID$)\n\
248  \n\
249  mantaMsg('Liquid step / s$ID$.frame: ' + str(s$ID$.frame))\n\
250  liquid_step_$ID$()\n\
251  \n\
252  s$ID$.step()\n\
253  \n\
254  fluid_post_step_$ID$()\n";
255 
256 const std::string liquid_step =
257  "\n\
258 def liquid_step_$ID$():\n\
259  mantaMsg('Liquid step')\n\
260  \n\
261  mantaMsg('Advecting particles')\n\
262  pp_s$ID$.advectInGrid(flags=flags_s$ID$, vel=vel_s$ID$, integrationMode=IntRK4, deleteInObstacle=deleteInObstacle_s$ID$, stopInObstacle=False, skipNew=True)\n\
263  \n\
264  mantaMsg('Pushing particles out of obstacles')\n\
265  if using_obstacle_s$ID$ and using_fractions_s$ID$ and fracDistance_s$ID$ > 0:\n\
266  # Optional: Increase distance between fluid and obstacles (only obstacles, not borders)\n\
267  pushOutofObs(parts=pp_s$ID$, flags=flags_s$ID$, phiObs=phiObsIn_s$ID$, thresh=fracDistance_s$ID$)\n\
268  pushOutofObs(parts=pp_s$ID$, flags=flags_s$ID$, phiObs=phiObs_s$ID$)\n\
269  \n\
270  # save original states for later (used during mesh / secondary particle creation)\n\
271  # but only save the state at the beginning of an adaptive frame\n\
272  if not s$ID$.timePerFrame:\n\
273  phiTmp_s$ID$.copyFrom(phi_s$ID$)\n\
274  velTmp_s$ID$.copyFrom(vel_s$ID$)\n\
275  \n\
276  mantaMsg('Advecting phi')\n\
277  advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=phi_s$ID$, order=1) # first order is usually enough\n\
278  mantaMsg('Advecting velocity')\n\
279  advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=vel_s$ID$, order=2)\n\
280  \n\
281  # create level set of particles\n\
282  gridParticleIndex(parts=pp_s$ID$, flags=flags_s$ID$, indexSys=pindex_s$ID$, index=gpi_s$ID$)\n\
283  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\
284  \n\
285  # combine level set of particles with grid level set\n\
286  phi_s$ID$.addConst(1.) # shrink slightly\n\
287  phi_s$ID$.join(phiParts_s$ID$)\n\
288  extrapolateLsSimple(phi=phi_s$ID$, distance=narrowBandWidth_s$ID$+2, inside=True)\n\
289  extrapolateLsSimple(phi=phi_s$ID$, distance=3)\n\
290  phi_s$ID$.setBoundNeumann(0) # make sure no particles are placed at outer boundary\n\
291  \n\
292  if not domainClosed_s$ID$ or using_outflow_s$ID$:\n\
293  resetOutflow(flags=flags_s$ID$, phi=phi_s$ID$, parts=pp_s$ID$, index=gpi_s$ID$, indexSys=pindex_s$ID$)\n\
294  flags_s$ID$.updateFromLevelset(phi_s$ID$)\n\
295  \n\
296  # combine particle velocities with advected grid velocities\n\
297  if using_apic_s$ID$:\n\
298  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\
299  else:\n\
300  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\
301  \n\
302  extrapolateMACFromWeight(vel=velParts_s$ID$, distance=2, weight=mapWeights_s$ID$)\n\
303  combineGridVel(vel=velParts_s$ID$, weight=mapWeights_s$ID$, combineVel=vel_s$ID$, phi=phi_s$ID$, narrowBand=combineBandWidth_s$ID$, thresh=0)\n\
304  velOld_s$ID$.copyFrom(vel_s$ID$)\n\
305  \n\
306  # forces & pressure solve\n\
307  addGravity(flags=flags_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, scale=False)\n\
308  \n\
309  mantaMsg('Adding external forces')\n\
310  addForceField(flags=flags_s$ID$, vel=vel_s$ID$, force=forces_s$ID$)\n\
311  \n\
312  extrapolateMACSimple(flags=flags_s$ID$, vel=vel_s$ID$, distance=2, intoObs=True if using_fractions_s$ID$ else False)\n\
313  \n\
314  # vel diffusion / viscosity!\n\
315  if using_diffusion_s$ID$:\n\
316  mantaMsg('Viscosity')\n\
317  # diffusion param for solve = const * dt / dx^2\n\
318  alphaV = kinViscosity_s$ID$ * s$ID$.timestep * float(res_s$ID$*res_s$ID$)\n\
319  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\
320  cgSolveDiffusion(flags_s$ID$, vel_s$ID$, alphaV)\n\
321  \n\
322  mantaMsg('Curvature')\n\
323  getLaplacian(laplacian=curvature_s$ID$, grid=phi_s$ID$)\n\
324  curvature_s$ID$.clamp(-1.0, 1.0)\n\
325  \n\
326  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\
327  if using_viscosity_s$ID$:\n\
328  viscosity_s$ID$.setConst(viscosityValue_s$ID$)\n\
329  applyViscosity(flags=flags_s$ID$, phi=phi_s$ID$, vel=vel_s$ID$, volumes=volumes_s$ID$, viscosity=viscosity_s$ID$)\n\
330  \n\
331  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\
332  if using_guiding_s$ID$:\n\
333  mantaMsg('Guiding and pressure')\n\
334  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\
335  else:\n\
336  mantaMsg('Pressure')\n\
337  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\
338  \n\
339  extrapolateMACSimple(flags=flags_s$ID$, vel=vel_s$ID$, distance=4, intoObs=True if using_fractions_s$ID$ else False)\n\
340  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\
341  \n\
342  if not using_fractions_s$ID$:\n\
343  extrapolateMACSimple(flags=flags_s$ID$, vel=vel_s$ID$)\n\
344  \n\
345  # set source grids for resampling, used in adjustNumber!\n\
346  pVel_pp$ID$.setSource(grid=vel_s$ID$, isMAC=True)\n\
347  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\
348  \n\
349  if using_apic_s$ID$:\n\
350  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\
351  else:\n\
352  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";
353 
354 const std::string liquid_step_mesh =
355  "\n\
356 def liquid_step_mesh_$ID$():\n\
357  mantaMsg('Liquid step mesh')\n\
358  \n\
359  # no upres: just use the loaded grids\n\
360  if upres_sm$ID$ <= 1:\n\
361  phi_sm$ID$.copyFrom(phi_s$ID$)\n\
362  \n\
363  # with upres: recreate grids\n\
364  else:\n\
365  interpolateGrid(target=phi_sm$ID$, source=phi_s$ID$)\n\
366  \n\
367  # create surface\n\
368  pp_sm$ID$.readParticles(pp_s$ID$)\n\
369  gridParticleIndex(parts=pp_sm$ID$, flags=flags_sm$ID$, indexSys=pindex_sm$ID$, index=gpi_sm$ID$)\n\
370  \n\
371  if using_final_mesh_s$ID$:\n\
372  mantaMsg('Liquid using improved particle levelset')\n\
373  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\
374  else:\n\
375  mantaMsg('Liquid using union particle levelset')\n\
376  unionParticleLevelset(pp_sm$ID$, pindex_sm$ID$, flags_sm$ID$, gpi_sm$ID$, phiParts_sm$ID$, meshRadiusFactor_s$ID$)\n\
377  \n\
378  phi_sm$ID$.addConst(1.) # shrink slightly\n\
379  phi_sm$ID$.join(phiParts_sm$ID$)\n\
380  extrapolateLsSimple(phi=phi_sm$ID$, distance=narrowBandWidth_s$ID$+2, inside=True)\n\
381  extrapolateLsSimple(phi=phi_sm$ID$, distance=3)\n\
382  phi_sm$ID$.setBoundNeumann(0) # make sure no particles are placed at outer boundary\n\
383  \n\
384  # Vert vel vector needs to pull data from vel grid with correct dim\n\
385  if using_speedvectors_s$ID$:\n\
386  interpolateMACGrid(target=vel_sm$ID$, source=vel_s$ID$)\n\
387  mVel_mesh$ID$.setSource(grid=vel_sm$ID$, isMAC=True)\n\
388  \n\
389  # Set 0.5 boundary at walls + account for extra wall thickness in fractions mode + account for grid scaling:\n\
390  # 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\
391  # Use -1 since setBound() starts counting at 0 (and additional -1 for fractions to account for solid/fluid interface cells)\n\
392  phi_sm$ID$.setBound(value=0.5, boundaryWidth=(upres_sm$ID$*2)-2 if using_fractions_s$ID$ else upres_sm$ID$-1)\n\
393  phi_sm$ID$.createMesh(mesh_sm$ID$)\n";
394 
395 const std::string liquid_step_particles =
396  "\n\
397 def liquid_step_particles_$ID$():\n\
398  mantaMsg('Secondary particles step')\n\
399  \n\
400  # no upres: just use the loaded grids\n\
401  if upres_sp$ID$ <= 1:\n\
402  vel_sp$ID$.copyFrom(velTmp_s$ID$)\n\
403  phiObs_sp$ID$.copyFrom(phiObs_s$ID$)\n\
404  phi_sp$ID$.copyFrom(phiTmp_s$ID$)\n\
405  phiOut_sp$ID$.copyFrom(phiOut_s$ID$)\n\
406  \n\
407  # with upres: recreate grids\n\
408  else:\n\
409  # create highres grids by interpolation\n\
410  interpolateMACGrid(target=vel_sp$ID$, source=velTmp_s$ID$)\n\
411  interpolateGrid(target=phiObs_sp$ID$, source=phiObs_s$ID$)\n\
412  interpolateGrid(target=phi_sp$ID$, source=phiTmp_s$ID$)\n\
413  interpolateGrid(target=phiOut_sp$ID$, source=phiOut_s$ID$)\n\
414  \n\
415  # phiIn not needed, bwidth to 0 because we are omitting flags.initDomain()\n\
416  setObstacleFlags(flags=flags_sp$ID$, phiObs=phiObs_sp$ID$, phiOut=phiOut_sp$ID$, phiIn=None, boundaryWidth=0)\n\
417  flags_sp$ID$.updateFromLevelset(levelset=phi_sp$ID$)\n\
418  \n\
419  # Actual secondary particle simulation\n\
420  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\
421  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\
422  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\
423  if using_snd_pushout_sp$ID$:\n\
424  pushOutofObs(parts=ppSnd_sp$ID$, flags=flags_sp$ID$, phiObs=phiObs_sp$ID$, shift=1.0)\n\
425  flipDeleteParticlesInObstacle(pts=ppSnd_sp$ID$, flags=flags_sp$ID$) # delete particles inside obstacle and outflow cells\n\
426  \n\
427  # Print debug information in the console\n\
428  if 0:\n\
429  debugGridInfo(flags=flags_sp$ID$, grid=trappedAir_sp$ID$, name='Trapped Air')\n\
430  debugGridInfo(flags=flags_sp$ID$, grid=waveCrest_sp$ID$, name='Wave Crest')\n\
431  debugGridInfo(flags=flags_sp$ID$, grid=kineticEnergy_sp$ID$, name='Kinetic Energy')\n";
432 
434 // IMPORT
436 
437 const std::string liquid_load_data =
438  "\n\
439 def liquid_load_data_$ID$(path, framenr, file_format, resumable):\n\
440  mantaMsg('Liquid load data')\n\
441  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\
442  fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$)\n\
443  \n\
444  copyVec3ToReal(source=vel_s$ID$, targetX=x_vel_s$ID$, targetY=y_vel_s$ID$, targetZ=z_vel_s$ID$)\n";
445 
446 const std::string liquid_load_mesh =
447  "\n\
448 def liquid_load_mesh_$ID$(path, framenr, file_format):\n\
449  mantaMsg('Liquid load mesh')\n\
450  dict = liquid_mesh_dict_s$ID$\n\
451  fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_mesh_s$ID$)\n\
452 \n\
453 def liquid_load_meshvel_$ID$(path, framenr, file_format):\n\
454  mantaMsg('Liquid load meshvel')\n\
455  dict = liquid_meshvel_dict_s$ID$\n\
456  fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_meshvel_s$ID$)\n";
457 
458 const std::string liquid_load_particles =
459  "\n\
460 def liquid_load_particles_$ID$(path, framenr, file_format, resumable):\n\
461  mantaMsg('Liquid load particles')\n\
462  dict = { **liquid_particles_dict_final_s$ID$, **liquid_particles_dict_resume_s$ID$ } if resumable else { **liquid_particles_dict_final_s$ID$ }\n\
463  fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_particles_s$ID$)\n";
464 
466 // EXPORT
468 
469 const std::string liquid_save_data =
470  "\n\
471 def liquid_save_data_$ID$(path, framenr, file_format, resumable):\n\
472  mantaMsg('Liquid save data')\n\
473  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\
474  if not withMPSave or isWindows:\n\
475  fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$)\n\
476  else:\n\
477  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";
478 
479 const std::string liquid_save_mesh =
480  "\n\
481 def liquid_save_mesh_$ID$(path, framenr, file_format):\n\
482  mantaMsg('Liquid save mesh')\n\
483  dict = liquid_mesh_dict_s$ID$\n\
484  if not withMPSave or isWindows:\n\
485  fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_mesh_s$ID$)\n\
486  else:\n\
487  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\
488 \n\
489 def liquid_save_meshvel_$ID$(path, framenr, file_format):\n\
490  mantaMsg('Liquid save mesh vel')\n\
491  dict = liquid_meshvel_dict_s$ID$\n\
492  if not withMPSave or isWindows:\n\
493  fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format)\n\
494  else:\n\
495  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";
496 
497 const std::string liquid_save_particles =
498  "\n\
499 def liquid_save_particles_$ID$(path, framenr, file_format, resumable):\n\
500  mantaMsg('Liquid save particles')\n\
501  dict = { **liquid_particles_dict_final_s$ID$, **liquid_particles_dict_resume_s$ID$ } if resumable else { **liquid_particles_dict_final_s$ID$ }\n\
502  if not withMPSave or isWindows:\n\
503  fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_particles_s$ID$)\n\
504  else:\n\
505  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";
506 
508 // STANDALONE MODE
510 
511 const std::string liquid_standalone =
512  "\n\
513 # Helper function to call cache load functions\n\
514 def load_data(frame, cache_resumable):\n\
515  liquid_load_data_$ID$(os.path.join(cache_dir, 'data'), frame, file_format_data, cache_resumable)\n\
516  if using_sndparts_s$ID$:\n\
517  liquid_load_particles_$ID$(os.path.join(cache_dir, 'particles'), frame, file_format_data, cache_resumable)\n\
518  if using_mesh_s$ID$:\n\
519  liquid_load_mesh_$ID$(os.path.join(cache_dir, 'mesh'), frame, file_format_mesh)\n\
520  if using_guiding_s$ID$:\n\
521  fluid_load_guiding_$ID$(os.path.join(cache_dir, 'guiding'), frame, file_format_data)\n\
522 \n\
523 # Helper function to call step functions\n\
524 def step(frame):\n\
525  liquid_adaptive_step_$ID$(frame)\n\
526  if using_mesh_s$ID$:\n\
527  liquid_step_mesh_$ID$()\n\
528  if using_sndparts_s$ID$:\n\
529  liquid_step_particles_$ID$()\n";
const std::string liquid_load_data
const std::string liquid_save_data
const std::string liquid_alloc_viscosity
const std::string liquid_variables
Definition: liquid_script.h:30
const std::string liquid_save_particles
const std::string liquid_standalone
const std::string liquid_variables_particles
Definition: liquid_script.h:58
const std::string liquid_load_mesh
const std::string liquid_alloc_particles
const std::string liquid_step
const std::string liquid_alloc
Definition: liquid_script.h:82
const std::string liquid_alloc_curvature
const std::string liquid_adaptive_step
const std::string liquid_load_particles
const std::string liquid_step_mesh
const std::string liquid_step_particles
const std::string liquid_alloc_mesh
const std::string liquid_init_phi
const std::string liquid_save_mesh