Skip to content

Instantly share code, notes, and snippets.

@nst
Created July 1, 2017 13:19
Show Gist options
  • Save nst/90e2cf3d18e1ab56bfc3a52ba1a27e90 to your computer and use it in GitHub Desktop.
Save nst/90e2cf3d18e1ab56bfc3a52ba1a27e90 to your computer and use it in GitHub Desktop.
Fluid simulation from 1D cellular automata
#!/usr/bin/env python
# Idea: YankeeMinstrel
# Python code: torstengrust
# Animated GIF: Nicolas Seriot, 2017-07-01
# https://www.reddit.com/r/cellular_automata/comments/6jhdfw/i_used_1dimensional_cellular_automata_to_make_a/
from PIL import Image, ImageDraw
from images2gif import writeGif
import os
def image(terrain, water):
assert(len(terrain) == len(water))
NB_CELLS = len(terrain)
CELL_WIDTH = 48
W, H = (NB_CELLS * CELL_WIDTH, 480)
H_FACTOR = 10
img = Image.new("RGB", (W, H), "white")
draw = ImageDraw.Draw(img)
for i in range(NB_CELLS):
t_x0 = i * CELL_WIDTH
t_y0 = 0
t_x1 = t_x0 + CELL_WIDTH
t_y1 = terrain[i] * H_FACTOR
w_x0 = t_x0
w_y0 = t_y1
w_x1 = t_x1
w_y1 = w_y0 + water[i] * H_FACTOR
draw.rectangle([(t_x0, t_y0), (t_x1, t_y1)], fill="brown", outline="white")
draw.rectangle([(w_x0, w_y0), (w_x1, w_y1)], fill="blue", outline="white")
return img.transpose(Image.FLIP_TOP_BOTTOM)
images = []
##
ground = [50, 1, 5, 8,12, 9, 5, 3, 2, 4, 8,12,15,20,50] # elevation
water = [ 0,20,20, 0, 0, 0, 0, 0, 0, 0,20,25,20,20, 0] # water volume
width = len(ground)
energy = [0]*width
for iter in range(24*5): # number of iterations to run
dwater = [0]*width
denergy = [0]*width
for x in range(1,width-1):
if ground[x] + water[x] - energy[x] > ground[x-1] + water[x-1] + energy[x-1]:
flow = min(water[x], ground[x] + water[x] - energy[x] - ground[x-1] - water[x-1] - energy[x-1]) / 4.0
dwater[x-1] += flow
dwater[x] += -flow
denergy[x-1] += -energy[x-1] / 2 - flow
if ground[x] + water[x] + energy[x] > ground[x+1] + water[x+1] - energy[x+1]:
flow = min(water[x], ground[x] + water[x] + energy[x] - ground[x+1] - water[x+1] + energy[x+1]) / 4.0
dwater[x+1] += flow
dwater[x] += -flow
denergy[x+1] += -energy[x+1] / 2 + flow
water = [sum(w) for w in zip(water, dwater)]
energy = [sum(e) for e in zip(energy, denergy)]
img = image(ground, water)
images.append(img)
filename = "eca_fluid_sim.gif"
writeGif(filename, images, duration=1/25.)
#os.system("open -a Safari %s" % filename)
@svnt
Copy link

svnt commented Aug 14, 2017

Neat! I converted it into JS -> https://codepen.io/svnt/pen/BdwBLp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment