Skip to content

Instantly share code, notes, and snippets.

@juliusgeo
Last active December 27, 2025 05:31
Show Gist options
  • Select an option

  • Save juliusgeo/2e63efa2f9a61aa5e94d86b9b53444eb to your computer and use it in GitHub Desktop.

Select an option

Save juliusgeo/2e63efa2f9a61aa5e94d86b9b53444eb to your computer and use it in GitHub Desktop.

Revisions

  1. juliusgeo revised this gist Jun 20, 2023. 1 changed file with 25 additions and 80 deletions.
    105 changes: 25 additions & 80 deletions main.py
    Original file line number Diff line number Diff line change
    @@ -1,81 +1,26 @@
    import os
    timestep = 1.0 / 60
    gravity = -9.81
    s_x, s_y = 10, 20
    u = v = [[0.0 for _ in range(s_y)] for _ in range(s_x)]
    pressures = [[0.0 for _ in range(s_y)] for _ in range(s_x)]
    states = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [0, 1, 1, 1, 1, 0, 0.1, 0, 0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0, 0, 0, 0],
    [0, 1, 1, 1, 1, 1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0, 0, 0, 0, 0],
    [0, 1, 1, 1, 1, 1, 0.1, 0.1, 0.1, 0.10, 0.1, 0.1, 0.1, 0.1, 0.1, 0, 0, 0, 0, 0],
    [0, 0.1, 0, 1, 1, 1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0, 0, 0, 0, 0],
    [0,0.1,0,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0,0,0,0,0,0,],
    [0, 0.1, 0, 0.2, 0.1, 0.1, 0.1, 0, 0.1, 0.1, 0.1, 0.1, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0.1, 0, 0, 0.2, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    ]
    C = 1000.0 / timestep
    loop = [(i, j) for i in range(1, len(u) - 1) for j in range(1, len(u[0]) - 1)]
    clamp = lambda x, size: 0 if x <= 0 else size - 1 if x >= size else x
    sample_field = lambda i, j, field: (
    x0 := clamp(int((i - 0.5)), s_x - 1),
    tx := ((i - 0.5) - x0),
    x1 := clamp(x0 + 1, s_x - 1),
    y0 := clamp(int((j - 0.5)), s_y - 1),
    ty := ((j - 0.5) - y0),
    y1 := clamp(y0 + 1, s_y - 1),
    sx := 1.0 - tx,
    sy := 1.0 - ty,
    sx * sy * field[x0][y0]
    + tx * sy * field[x1][y0]
    + tx * ty * field[x1][y1]
    + sx * ty * field[x0][y1],
    )[-1]
    ses = (".", ":", "!", "*", "o", "e", "&", "#", "%", "@")
    for _ in range(10000):
    u = [[i + timestep * gravity for i in t] for t in u]
    v = [[i + timestep * gravity for i in t] for t in v]
    for i, j in loop:
    l, r, t, b = u[i][j], u[i + 1][j], v[i][j], v[i][j + 1]
    ls, rs, ts, bs = (
    states[i - 1][j],
    states[i + 1][j],
    states[i][j - 1],
    states[i][j + 1],
    )
    if states[i][j] == 0:
    continue
    s = sum((ls, rs, ts, bs))
    d = (l - r) + (t - b)
    p = (-d / s) * 1.9
    pressures[i][j] += p * C
    u[i][j], v[i + 1][j], u[i][j], v[i][j + 1] = (
    l + d * ls,
    r + d * rs,
    t + d * ts,
    b + d * bs,
    )
    for i in range(len(u)):
    u[i][0], u[i][s_y - 1] = u[i][1], u[i][s_y - 2]
    for j in range(len(v[0])):
    v[0][j], v[s_x - 1][j] = v[1][j], v[s_x - 2][j]
    new_u = new_v = [[0.0 for _ in range(s_y)] for _ in range(s_x)]
    for i, j in loop:
    if states[i][j] != 0 and states[i - 1][j] != 0:
    x, y = i, j + 0.5
    nu, nv = u[i][j], sum((v[i][j], v[i + 1][j], v[i][j], v[i][j + 1])) / 4
    x -= timestep * nu
    y -= timestep * nv
    new_u[i][j] = sample_field(int(x), int(y), u)
    if states[i][j] != 0 and states[i][j - 1] != 0:
    x, y = i + 0.5, j
    nu, nv = sum((u[i][j], u[i + 1][j], u[i][j], u[i][j + 1])) / 4, v[i][j]
    x -= timestep * nu
    y -= timestep * nv
    new_v[i][j] = sample_field(int(x), int(y), v)
    u, v = new_u, new_v
    os.system("clear")
    for line in pressures:
    print("".join([ses[min(int(abs(i) / C) // 10, 9)] for i in line]), flush=True)
    timestep=1./60
    gravity=-9.81
    tg=timestep*gravity
    s_x,s_y=10,20
    u=v=[[.0 for A in range(s_y)]for A in range(s_x)]
    pr=[[.0 for A in range(s_y)]for A in range(s_x)]
    st=[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[0,1,1,1,1,0,.1,0,0,.1,.1,.1,.1,.1,.1,.1,0,0,0,0],[0,1,1,1,1,1,.1,.1,.1,.1,.1,.1,.1,.1,.1,0,0,0,0,0],[0,1,1,1,1,1,.1,.1,.1,.1,.1,.1,.1,.1,.1,0,0,0,0,0],[0,.1,0,1,1,1,.1,.1,.1,.1,.1,.1,.1,.1,.1,0,0,0,0,0],[0,.1,0,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,0,0,0,0,0,0],[0,.1,0,.2,.1,.1,.1,0,.1,.1,.1,.1,0,0,0,0,0,0,0,0],[0,.1,0,0,.2,.1,.1,0,.1,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]
    C=1e3/timestep
    loop=[(A,B)for A in range(1,len(u)-1)for B in range(1,len(u[0])-1)]
    cl=lambda x,size:0 if x<=0 else size-1 if x>=size else x
    sf=lambda i,j,field:((A:=cl(int(i-.5),s_x-1)),(C:=i-.5-A),(E:=cl(A+1,s_x-1)),(B:=cl(int(j-.5),s_y-1)),(D:=j-.5-B),(F:=cl(B+1,s_y-1)),(G:=1.-C),(H:=1.-D),G*H*field[A][B]+C*H*field[E][B]+C*D*field[E][F]+G*D*field[A][F])[-1]
    ses='.',':','!','*','o','e','&','#','%','@'
    for _ in range(2**10):
    u=[[A+tg for A in A]for A in u];v=[[A+tg for A in A]for A in v]
    for(i,j)in loop:
    l,r,t,b=u[i][j],u[i+1][j],v[i][j],v[i][j+1];ls,rs,ts,bs=st[i-1][j],st[i+1][j],st[i][j-1],st[i][j+1]
    if st[i][j]==0:continue
    s=ls+rs+ts+bs;d=l-r+t-b;p=-d/s*1.9;pr[i][j]+=p*C;u[i][j],v[i+1][j],u[i][j],v[i][j+1]=l+d*ls,r+d*rs,t+d*ts,b+d*bs
    for i in range(len(u)):u[i][0],u[i][s_y-1],v[0][j],v[s_x-1][j]=u[i][1],u[i][s_y-2],v[1][j],v[s_x-2][j]
    new_u=new_v=[[.0 for A in range(s_y)]for A in range(s_x)]
    for(i,j)in loop:
    if st[i][j]!=0 and st[i-1][j]!=0:x,y=i,j+.5;nu,nv=u[i][j],sum((v[i][j],v[i+1][j],v[i][j],v[i][j+1]))/4;x-=timestep*nu;y-=timestep*nv;new_u[i][j]=sf(x//1,y//1,u)
    if st[i][j]!=0 and st[i][j-1]!=0:x,y=i+.5,j;nu,nv=sum((u[i][j],u[i+1][j],u[i][j],u[i][j+1]))/4,v[i][j];x-=timestep*nu;y-=timestep*nv;new_v[i][j]=sf(x//1,y//1,v)
    u,v=new_u,new_v;os.system('clear')
    for line in pr:print(''.join([ses[min(int(abs(A)/C)//10,9)]for A in line]),flush=True)
  2. juliusgeo created this gist Jun 20, 2023.
    81 changes: 81 additions & 0 deletions main.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,81 @@
    import os
    timestep = 1.0 / 60
    gravity = -9.81
    s_x, s_y = 10, 20
    u = v = [[0.0 for _ in range(s_y)] for _ in range(s_x)]
    pressures = [[0.0 for _ in range(s_y)] for _ in range(s_x)]
    states = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [0, 1, 1, 1, 1, 0, 0.1, 0, 0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0, 0, 0, 0],
    [0, 1, 1, 1, 1, 1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0, 0, 0, 0, 0],
    [0, 1, 1, 1, 1, 1, 0.1, 0.1, 0.1, 0.10, 0.1, 0.1, 0.1, 0.1, 0.1, 0, 0, 0, 0, 0],
    [0, 0.1, 0, 1, 1, 1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0, 0, 0, 0, 0],
    [0,0.1,0,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0,0,0,0,0,0,],
    [0, 0.1, 0, 0.2, 0.1, 0.1, 0.1, 0, 0.1, 0.1, 0.1, 0.1, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0.1, 0, 0, 0.2, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    ]
    C = 1000.0 / timestep
    loop = [(i, j) for i in range(1, len(u) - 1) for j in range(1, len(u[0]) - 1)]
    clamp = lambda x, size: 0 if x <= 0 else size - 1 if x >= size else x
    sample_field = lambda i, j, field: (
    x0 := clamp(int((i - 0.5)), s_x - 1),
    tx := ((i - 0.5) - x0),
    x1 := clamp(x0 + 1, s_x - 1),
    y0 := clamp(int((j - 0.5)), s_y - 1),
    ty := ((j - 0.5) - y0),
    y1 := clamp(y0 + 1, s_y - 1),
    sx := 1.0 - tx,
    sy := 1.0 - ty,
    sx * sy * field[x0][y0]
    + tx * sy * field[x1][y0]
    + tx * ty * field[x1][y1]
    + sx * ty * field[x0][y1],
    )[-1]
    ses = (".", ":", "!", "*", "o", "e", "&", "#", "%", "@")
    for _ in range(10000):
    u = [[i + timestep * gravity for i in t] for t in u]
    v = [[i + timestep * gravity for i in t] for t in v]
    for i, j in loop:
    l, r, t, b = u[i][j], u[i + 1][j], v[i][j], v[i][j + 1]
    ls, rs, ts, bs = (
    states[i - 1][j],
    states[i + 1][j],
    states[i][j - 1],
    states[i][j + 1],
    )
    if states[i][j] == 0:
    continue
    s = sum((ls, rs, ts, bs))
    d = (l - r) + (t - b)
    p = (-d / s) * 1.9
    pressures[i][j] += p * C
    u[i][j], v[i + 1][j], u[i][j], v[i][j + 1] = (
    l + d * ls,
    r + d * rs,
    t + d * ts,
    b + d * bs,
    )
    for i in range(len(u)):
    u[i][0], u[i][s_y - 1] = u[i][1], u[i][s_y - 2]
    for j in range(len(v[0])):
    v[0][j], v[s_x - 1][j] = v[1][j], v[s_x - 2][j]
    new_u = new_v = [[0.0 for _ in range(s_y)] for _ in range(s_x)]
    for i, j in loop:
    if states[i][j] != 0 and states[i - 1][j] != 0:
    x, y = i, j + 0.5
    nu, nv = u[i][j], sum((v[i][j], v[i + 1][j], v[i][j], v[i][j + 1])) / 4
    x -= timestep * nu
    y -= timestep * nv
    new_u[i][j] = sample_field(int(x), int(y), u)
    if states[i][j] != 0 and states[i][j - 1] != 0:
    x, y = i + 0.5, j
    nu, nv = sum((u[i][j], u[i + 1][j], u[i][j], u[i][j + 1])) / 4, v[i][j]
    x -= timestep * nu
    y -= timestep * nv
    new_v[i][j] = sample_field(int(x), int(y), v)
    u, v = new_u, new_v
    os.system("clear")
    for line in pressures:
    print("".join([ses[min(int(abs(i) / C) // 10, 9)] for i in line]), flush=True)