-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsolver.lua
160 lines (130 loc) · 3.17 KB
/
solver.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
--[[
This solver is based on the code from 'Real-time Fluid Dynamics for Games' by Jos Stam.
http://www.dgp.toronto.edu/people/stam/reality/Research/pdf/GDC03.pdf
]]
local solver = {}
local N = 64
local N1, N2 = N + 1, N + 2
setfenv(1,solver)
function add_source(N, x, s, dt)
local i, size = 0,(N2)*(N2)
for i=1,size do
x[i] = x[i] + dt * s[i]
end
end
function set_bnd(N, b, x)
local N2N, N2N1,i = N2*N, N2*N1
for i=1,N do
local N2i = N2*i
local _0i,_1i,_Ni,_N1i = N2i,1+N2i,N+N2i,N1+N2i
local _i0,_i1,_iN,_iN1 = i,i+N2,i+N2N,i+(N2N1)
local sign = 1
if b == 1 then sign = -1 end
x[_0i] = x[_1i] * sign
x[_N1i] = x[_Ni] * sign
sign = 1
if b == 2 then sign = -1 end
x[_i0] = x[_i1] * sign
x[_iN1] = x[_iN] * sign
end
x[0] = 0.5 * ( x[1] + x[N2] )
x[N2N1] = 0.5 * ( x[1+N2N1] + x[N2N] )
x[N1] = 0.5 * ( x[N] + x[N1+N2] )
x[N1+N2N1] = 0.5 * ( x[N+N2N1] + x[N1+N2N] )
end
function lin_solve(N, b, x, x0, a, c)
local i, j, k
for k=1,20 do
for i = 1, N do
for j=1,N do
x[i+N2*j] = ( x0[i+N2*j] + a * (x[(i-1)+N2*j] + x[(i+1)+N2*j]+x[i+N2*(j-1)] + x[i+N2*(j+1)]) ) / c;
end
end
set_bnd ( N, b, x )
end
end
function diffuse( N, b, x, x0, diff, dt )
local a = dt*diff*N*N
lin_solve( N, b, x, x0, a, 1+4*a )
end
function advect (N, b, d, d0, u, v, dt )
local i, j, i0, j0, i1, j1;
local x, y, s0, t0, s1, t1, dt0;
dt0 = dt*N;
for i = 1, N do
for j = 1, N do
x = i-dt0*u[i+N2*j];
y = j-dt0*v[i+N2*j];
if x < 0.5 then
x = 0.5
end
if x > N+0.5 then
x = N+0.5
end
i0 = x - x%1
i1 = i0+1;
if y < 0.5 then
y = 0.5
end
if y > N+0.5 then
y = N+0.5
end
j0 = y - y%1
j1 = j0+1
s1 = x-i0
s0 = 1-s1
t1 = y-j0
t0 = 1-t1
d[i+N2*j] = s0 * ( t0 * d0[i0+N2*j0] + t1 * d0[i0+N2*j1] )
+ s1 * ( t0 * d0[i1+N2*j0] + t1 * d0[i1+N2*j1] )
end
end
set_bnd ( N, b, d )
end
function project(N, u, v, p, div)
local i, j
for i = 1, N do
for j=1,N do
div[i+N2*j] = -0.5*(u[(i+1)+N2*j]-u[(i-1)+N2*j]+v[i+N2*(j+1)]-v[i+N2*(j-1)])/N;
p[i+N2*j] = 0;
end
end
set_bnd ( N, 0, div );
set_bnd ( N, 0, p );
lin_solve ( N, 0, p, div, 1, 4 );
for i = 1, N do
for j=1,N do
local index = i+N2*j
u[index] = u[index] - 0.5*N*(p[(i+1)+N2*j]-p[(i-1)+N2*j]);
v[index] = v[index] - 0.5*N*(p[i+N2*(j+1)]-p[i+N2*(j-1)]);
end
end
set_bnd ( N, 1, u );
set_bnd ( N, 2, v );
end
function dens_step ( N, x, x0, u, v, diff, dt )
add_source ( N, x, x0, dt );
x0,x = x,x0
diffuse ( N, 0, x, x0, diff, dt );
x0,x = x,x0
advect ( N, 0, x, x0, u, v, dt );
end
function vel_step ( N, u, v, u0, v0, visc, dt )
add_source ( N, u, u0, dt );
add_source ( N, v, v0, dt );
u0,u = u,u0
diffuse ( N, 1, u, u0, visc, dt );
v0,v = v,v0
diffuse ( N, 2, v, v0, visc, dt );
project ( N, u, v, u0, v0 );
u0,u = u,u0
v0,v = v,v0
advect ( N, 1, u, u0, u0, v0, dt );
advect ( N, 2, v, v0, u0, v0, dt );
project ( N, u, v, u0, v0 );
end
function init(size)
N = size
N1, N2 = N + 1, N + 2
end
return solver