https://github.com/thunil/ofblend
Tip revision: aef880de2c500a7f7828fe93647299e8bc0170aa authored by Nils Thuerey on 06 December 2017, 08:13:20 UTC
Merge pull request #1 from qinenergy/patch-1
Merge pull request #1 from qinenergy/patch-1
Tip revision: aef880d
flip05_nbflip.py
##############################################################
# Flip scene with narrow-band FLIP
#
# Reference:
# [1] Narrow Band FLIP for Liquid Simulations
# F. Ferstl, R. Ando, R. Westermann, C. Wojtan, N. Thuerey
# Computer Graphics Forum (Proc. Eurographics 2016)
##############################################################
from manta import *
# Toggle between regular FLIP and NB-FLIP
narrowBand = True
# Choose dimension (2 or 3) and resolution
dim = 3
res = 64
# Configuration
narrowBandWidth = 3; # Narrow band width in cells (= R in [1])
combineBandWidth = narrowBandWidth - 1; # Combine band width in cells (= r in [1])
# Solver params
gs = vec3(res,res,res)
if dim==2: gs.z = 1;
s = Solver(name='main', gridSize = gs, dim=dim)
mantaMsg("Narrow band: %i" % narrowBand)
mantaMsg('Solver grid resolution: %i x %i x %i' % (gs.x, gs.y, gs.z))
# Adaptive time stepping
s.frameLength = 1.0 # length of one frame (in "world time")
s.timestep = 1.0
s.timestepMin = 0.5 # time step range
s.timestepMax = 1.0
s.cfl = 5.0 # maximal velocity per cell, 0 to use fixed timesteps
gravity = (0,-0.003,0)
minParticles = pow(2,dim)
# Prepare grids and particles
flags = s.create(FlagGrid)
phiParts = s.create(LevelsetGrid)
phi = s.create(LevelsetGrid)
pressure = s.create(RealGrid)
vel = s.create(MACGrid)
velOld = s.create(MACGrid)
velParts = s.create(MACGrid)
mapWeights = s.create(MACGrid)
pp = s.create(BasicParticleSystem)
pVel = pp.create(PdataVec3)
mesh = s.create(Mesh)
# Acceleration data for particle nbs
pindex = s.create(ParticleIndexSystem)
gpi = s.create(IntGrid)
# Geometry in world units (to be converted to grid space upon init)
flags.initDomain(boundaryWidth=0)
phi.initFromFlags(flags)
# A simple breaking dam
fluidBasin = Box( parent=s, p0=gs*vec3(0,0,0), p1=gs*vec3(1.0,0.15,1.0))
phi.join( fluidBasin.computeLevelset() )
fluidDam = Box( parent=s, p0=gs*vec3(0,0.15,0), p1=gs*vec3(0.4,0.5,0.8))
phi.join( fluidDam.computeLevelset() )
flags.updateFromLevelset(phi)
sampleLevelsetWithParticles( phi=phi, flags=flags, parts=pp, discretization=2, randomness=0.4 )
mapGridToPartsVec3(source=vel, parts=pp, target=pVel )
if 1 and (GUI):
gui = Gui()
gui.show( dim==3 )
#gui.pause()
# Main loop
step = -1
while s.frame < 200:
step = step + 1
maxVel = vel.getMaxValue()
s.adaptTimestep( maxVel )
mantaMsg( '\nFrame %i, step %i, time-step size %f' % (s.frame, step, s.timestep) )
# Advect particles and grid phi
# Note: Grid velocities are extrapolated at the end of each step
pp.advectInGrid(flags=flags, vel=vel, integrationMode=IntRK4, deleteInObstacle=False )
advectSemiLagrange(flags=flags, vel=vel, grid=phi, order=1)
flags.updateFromLevelset(phi)
# Advect grid velocity
if narrowBand:
advectSemiLagrange(flags=flags, vel=vel, grid=vel, order=2)
# Create level set of particles
gridParticleIndex( parts=pp , flags=flags, indexSys=pindex, index=gpi )
unionParticleLevelset( pp, pindex, flags, gpi, phiParts )
if narrowBand:
# Combine level set of particles with grid level set
phi.addConst(1.); # shrink slightly
phi.join( phiParts );
extrapolateLsSimple(phi=phi, distance=narrowBandWidth+2, inside=True )
else:
# Overwrite grid level set with level set of particles
phi.copyFrom( phiParts );
extrapolateLsSimple(phi=phi, distance=4, inside=True )
extrapolateLsSimple(phi=phi, distance=3 )
flags.updateFromLevelset(phi)
# Make sure we have velocities throught liquid region
if narrowBand:
# Combine particles velocities with advected grid velocities
mapPartsToMAC(vel=velParts, flags=flags, velOld=velOld, parts=pp, partVel=pVel, weight=mapWeights)
extrapolateMACFromWeight( vel=velParts , distance=2, weight=mapWeights )
combineGridVel(vel=velParts, weight=mapWeights , combineVel=vel, phi=phi, narrowBand=combineBandWidth, thresh=0)
velOld.copyFrom(vel)
else:
# Map particle velocities to grid
mapPartsToMAC(vel=vel, flags=flags, velOld=velOld, parts=pp, partVel=pVel, weight=mapWeights)
extrapolateMACFromWeight( vel=vel , distance=2, weight=mapWeights )
# Forces & pressure solve
addGravity(flags=flags, vel=vel, gravity=gravity)
setWallBcs(flags=flags, vel=vel)
solvePressure(flags=flags, vel=vel, pressure=pressure, phi=phi)
setWallBcs(flags=flags, vel=vel)
# Extrapolate velocities
extrapolateMACSimple( flags=flags, vel=vel, distance=(int(maxVel*1.25 + 2.)) )
# Update particle velocities
flipVelocityUpdate(vel=vel, velOld=velOld, flags=flags, parts=pp, partVel=pVel, flipRatio=0.95 )
if dim==3:
phi.createMesh(mesh)
# Resample particles
pVel.setSource( vel, isMAC=True ) # Set source grids for resampling, used in adjustNumber!
if narrowBand:
phi.setBoundNeumann(0) # make sure no particles are placed at outer boundary
adjustNumber( parts=pp, vel=vel, flags=flags, minParticles=1*minParticles, maxParticles=2*minParticles, phi=phi, narrowBand=narrowBandWidth )
else:
adjustNumber( parts=pp, vel=vel, flags=flags, minParticles=1*minParticles, maxParticles=2*minParticles, phi=phi )
s.step()