#
# Simple flip with level set and basic resampling
#
from manta import *
# solver params
dim = 3
res = 64
#res = 128
gs = vec3(res,res,res)
if (dim==2):
gs.z=1
s = Solver(name='main', gridSize = gs, dim=dim)
s.timestep = 0.8
minParticles = pow(2,dim)
# save particles for separate surface generation pass?
saveParts = False
# size of particles
radiusFactor = 1.0
# prepare grids and particles
flags = s.create(FlagGrid)
phi = s.create(LevelsetGrid)
vel = s.create(MACGrid)
velOld = s.create(MACGrid)
pressure = s.create(RealGrid)
tmpVec3 = s.create(VecGrid)
tstGrid = s.create(RealGrid)
pp = s.create(BasicParticleSystem)
pVel = pp.create(PdataVec3)
# test real value, not necessary for simulation
pTest = pp.create(PdataReal)
mesh = s.create(Mesh)
# acceleration data for particle nbs
pindex = s.create(ParticleIndexSystem)
gpi = s.create(IntGrid)
# scene setup, 0=breaking dam, 1=drop into pool
setup = 1
bWidth=1
flags.initDomain(boundaryWidth=bWidth)
fluidVel = 0
fluidSetVel = 0
if setup==0:
# breaking dam
fluidbox = Box( parent=s, p0=gs*vec3(0,0,0), p1=gs*vec3(0.4,0.6,1)) # breaking dam
#fluidbox = Box( parent=s, p0=gs*vec3(0.4,0.72,0.4), p1=gs*vec3(0.6,0.92,0.6)) # centered falling block
phi = fluidbox.computeLevelset()
elif setup==1:
# falling drop
fluidBasin = Box( parent=s, p0=gs*vec3(0,0,0), p1=gs*vec3(1.0,0.1,1.0)) # basin
dropCenter = vec3(0.5,0.3,0.5)
dropRadius = 0.1
fluidDrop = Sphere( parent=s , center=gs*dropCenter, radius=res*dropRadius)
fluidVel = Sphere( parent=s , center=gs*dropCenter, radius=res*(dropRadius+0.05) )
fluidSetVel= vec3(0,-1,0)
phi = fluidBasin.computeLevelset()
phi.join( fluidDrop.computeLevelset() )
flags.updateFromLevelset(phi)
#setOpenBound(flags,bWidth,'xX',FlagOutflow|FlagEmpty)
sampleLevelsetWithParticles( phi=phi, flags=flags, parts=pp, discretization=2, randomness=0.05 )
if fluidVel!=0:
# set initial velocity
fluidVel.applyToGrid( grid=vel , value=fluidSetVel )
mapGridToPartsVec3(source=vel, parts=pp, target=pVel )
# testing the real channel while resampling - original particles
# will have a value of 0.1, new particle will get a value from the tstGrid
testInitGridWithPos(tstGrid)
pTest.setConst( 0.1 )
# save reference any grid, to automatically determine grid size
if saveParts:
pressure.save( 'ref_flipParts_0000.uni' );
if 1 and (GUI):
gui = Gui()
gui.show()
#gui.pause()
#main loop
for t in range(250):
mantaMsg('\nFrame %i, simulation time %f' % (s.frame, s.timeTotal))
# FLIP
pp.advectInGrid(flags=flags, vel=vel, integrationMode=IntRK4, deleteInObstacle=False )
# make sure we have velocities throught liquid region
mapPartsToMAC(vel=vel, flags=flags, velOld=velOld, parts=pp, partVel=pVel, weight=tmpVec3 )
extrapolateMACFromWeight( vel=vel , distance=2, weight=tmpVec3 ) # note, tmpVec3 could be free'd now...
markFluidCells( parts=pp, flags=flags )
# create approximate surface level set, resample particles
gridParticleIndex( parts=pp , flags=flags, indexSys=pindex, index=gpi )
unionParticleLevelset( pp, pindex, flags, gpi, phi , radiusFactor )
resetOutflow(flags=flags,parts=pp,index=gpi,indexSys=pindex)
# extend levelset somewhat, needed by particle resampling in adjustNumber
extrapolateLsSimple(phi=phi, distance=4, inside=True);
# forces & pressure solve
addGravity(flags=flags, vel=vel, gravity=(0,-0.001,0))
setWallBcs(flags=flags, vel=vel)
solvePressure(flags=flags, vel=vel, pressure=pressure, phi=phi)
setWallBcs(flags=flags, vel=vel)
# set source grids for resampling, used in adjustNumber!
pVel.setSource( vel, isMAC=True )
pTest.setSource( tstGrid );
adjustNumber( parts=pp, vel=vel, flags=flags, minParticles=1*minParticles, maxParticles=2*minParticles, phi=phi, radiusFactor=radiusFactor )
# make sure we have proper velocities
extrapolateMACSimple( flags=flags, vel=vel )
flipVelocityUpdate(vel=vel, velOld=velOld, flags=flags, parts=pp, partVel=pVel, flipRatio=0.97 )
if (dim==3):
phi.createMesh(mesh)
#s.printMemInfo()
s.step()
# generate data for flip03_gen.py surface generation scene
if saveParts:
pp.save( 'flipParts_%04d.uni' % t );
if 0 and (GUI):
gui.screenshot( 'flip02_%04d.png' % t );