I found nice realtime fluid simulation code created with c++. I converted it to vb.net but i have run into trouble. You can find original c++ code here: http://www.dgp.toronto.edu/people/st...DROM_GDC03.zip . Here's my vb.net solver part of code:
Simulation seems to become very unstable with vb.net. I think problem is somewhere in vel_step, which calculates velocity components. Because when displaying velocity vectorfield its very unstable and flickering. When I tried to debug code I saw that some of the values become -1.#IND which means I'm dividing with zero or doing something else wrong. But I havent found any part where division by zero might happen and I think this is not the case.
I have checked and rechecked my code. Calculations are identical to c++. Maybe there's something wrong with .net and it cant perform this amount of calculations. :D
Code:
Sub set_bnd(ByVal N As Integer, ByVal b As Integer, ByVal x(,) As Single)
Dim i As Integer
For i = 1 To (N + 1)
If b = 1 Then
x(0, i) = -x(1, i)
Else
x(0, i) = x(1, i)
End If
If b = 1 Then
x(N + 1, i) = -x(N, i)
Else
x(N + 1, i) = x(N, i)
End If
If b = 2 Then
x(i, 0) = -x(i, 1)
Else
x(i, 0) = x(i, 1)
End If
If b = 2 Then
x(i, N + 1) = -x(i, N)
Else
x(i, N + 1) = x(i, N)
End If
Next
x(0, 0) = 0.5F * (x(1, 0) + x(0, 1))
x(0, N + 1) = 0.5F * (x(1, N + 1) + x(0, N))
x(N + 1, 0) = 0.5F * (x(N, 0) + x(N + 1, 1))
x(N + 1, N + 1) = 0.5F * (x(N, N + 1) + x(N + 1, N))
End Sub
Sub lin_solve(ByVal N As Integer, ByVal b As Integer, ByVal x(,) As Single, ByVal x0(,) As Single, ByVal a As Single, ByVal c As Single)
Dim i, j, k As Integer
For k = 0 To 20
For i = 1 To N + 1
For j = 1 To N + 1
x(i, j) = (x0(i, j) + a * (x(i - 1, j) + x(i + 1, j) + x(i, j - 1) + x(i, j + 1))) / (c)
Next
Next
set_bnd(N, b, x)
Next
End Sub
Sub add_source(ByVal N As Integer, ByVal x(,) As Single, ByVal s(,) As Single, ByVal dt As Single)
Dim i, j As Integer
Dim size As Integer = (N + 2)
For i = 0 To size
For j = 0 To size
x(i, j) += dt * s(i, j)
Next
Next
End Sub
'Diffusion
Sub diffuse(ByVal N As Integer, ByVal b As Integer, ByVal x(,) As Single, ByVal x0(,) As Single, ByVal diff As Single, ByVal dt As Single)
Dim a As Single
a = dt * diff * N * N
lin_solve(N, b, x, x0, a, 1 + 4 * a)
End Sub
'Advection
Sub advect(ByVal N As Integer, ByVal b As Integer, ByVal d(,) As Single, ByVal d0(,) As Single, ByVal u(,) As Single, ByVal v(,) As Single, ByVal dt As Single)
Dim i, j, i0, j0, i1, j1 As Integer
Dim x, y, s0, t0, s1, t1, dt0 As Single
dt0 = dt * N
For i = 1 To N
For j = 1 To N
x = i - dt0 * u(i, j)
y = j - dt0 * v(i, j)
If x < 0.5F Then x = 0.5F
If x > (N + 0.5F) Then x = N + 0.5F
i0 = CInt(x)
i1 = i0 + 1
If y < 0.5F Then y = 0.5F
If y > (N + 0.5F) Then y = N + 0.5F
j0 = CInt(y)
j1 = j0 + 1
s1 = x - i0
s0 = 1 - s1
t1 = y - j0
t0 = 1 - t1
d(i, j) = s0 * (t0 * d0(i0, j0) + t1 * d0(i0, j1)) + s1 * (t0 * d0(i1, j0) + t1 * d0(i1, j1))
Next
Next
set_bnd(N, b, d)
End Sub
Sub project(ByVal N As Integer, ByVal u(,) As Single, ByVal v(,) As Single, ByVal p(,) As Single, ByVal div(,) As Single)
Dim i, j As Integer
Dim h As Single
h = 1.0F / N
For i = 1 To N + 1
For j = 1 To N + 1
div(i, j) = -0.5F * h * (u(i + 1, j) - u(i - 1, j) + v(i, j + 1) - v(i, j - 1))
p(i, j) = 0
Next
Next
set_bnd(N, 0, div)
set_bnd(N, 0, p)
lin_solve(N, 0, p, div, 1, 4)
For i = 1 To N + 1
For j = 1 To N + 1
u(i, j) -= 0.5F * (p(i + 1, j) - p(i - 1, j)) / h
v(i, j) -= 0.5F * (p(i, j + 1) - p(i, j - 1)) / h
Next
Next
set_bnd(N, 1, u)
set_bnd(N, 2, v)
End Sub
Sub dens_step(ByVal N As Integer, ByVal x(,) As Single, ByVal x0(,) As Single, ByVal u(,) As Single, ByVal v(,) As Single, ByVal diff As Single, ByVal dt As Single)
Array.Clear(temp, 0, Size1D)
add_source(N, x, x0, dt)
'Swap arrays
Array.Copy(x, temp, Size1D)
Array.Copy(x, x0, Size1D)
Array.Copy(temp, x, Size1D)
diffuse(N, 0, x, x0, diff, dt)
Array.Clear(temp, 0, Size1D)
'Swap arrays
Array.Copy(x, temp, Size1D)
Array.Copy(x, x0, Size1D)
Array.Copy(temp, x, Size1D)
advect(N, 0, x, x0, u, v, dt)
End Sub
Sub vel_step(ByVal N As Integer, ByVal u(,) As Single, ByVal v(,) As Single, ByVal u0(,) As Single, ByVal v0(,) As Single, ByVal visc As Single, ByVal dt As Single)
add_source(N, u, u0, dt)
add_source(N, v, v0, dt)
Array.Clear(temp, 0, Size1D)
Array.Copy(u, temp, Size1D)
Array.Copy(u, u0, Size1D)
Array.Copy(temp, u, Size1D)
diffuse(N, 1, u, u0, visc, dt)
Array.Clear(temp, 0, Size1D)
Array.Copy(v, temp, Size1D)
Array.Copy(v, v0, Size1D)
Array.Copy(temp, v, Size1D)
diffuse(N, 2, v, v0, visc, dt)
project(N, u, v, u0, v0)
Array.Clear(temp, 0, Size1D)
Array.Copy(u, temp, Size1D)
Array.Copy(u, u0, Size1D)
Array.Copy(temp, u, Size1D)
Array.Clear(temp, 0, Size1D)
Array.Copy(v, temp, Size1D)
Array.Copy(v, v0, Size1D)
Array.Copy(temp, v, Size1D)
advect(N, 1, u, u0, u0, v0, dt)
advect(N, 2, v, v0, u0, v0, dt)
project(N, u, v, u0, v0)
End Sub
End Class
I have checked and rechecked my code. Calculations are identical to c++. Maybe there's something wrong with .net and it cant perform this amount of calculations. :D
Comment