gambas-source-code/benchmark/nbody.gbs

213 lines
4.2 KiB
Text
Raw Permalink Normal View History

#!/usr/bin/env gbs3
Class Body
Static Private SOLAR_MASS As Float = 4 * Pi * Pi
Private Const DAYS_PER_YEAR As Float = 365.24
Public X As Float
Public Y As Float
Public Z As Float
Public VX As Float
Public VY As Float
Public VZ As Float
Public Mass As Float
Static Public Sub Jupiter() As Body
Dim P As New Body
p.x = 4.84143144246472090e+00
p.y = -1.16032004402742839e+00
p.z = -1.03622044471123109e-01
p.vx = 1.66007664274403694e-03 * DAYS_PER_YEAR
p.vy = 7.69901118419740425e-03 * DAYS_PER_YEAR
p.vz = -6.90460016972063023e-05 * DAYS_PER_YEAR
p.mass = 9.54791938424326609e-04 * SOLAR_MASS
return p
End
Static Public Sub Saturn() As Body
Dim P As New Body
p.x = 8.34336671824457987e+00
p.y = 4.12479856412430479e+00
p.z = -4.03523417114321381e-01
p.vx = -2.76742510726862411e-03 * DAYS_PER_YEAR
p.vy = 4.99852801234917238e-03 * DAYS_PER_YEAR
p.vz = 2.30417297573763929e-05 * DAYS_PER_YEAR
p.mass = 2.85885980666130812e-04 * SOLAR_MASS
return p
End
Static Public Sub Uranus() As Body
Dim P As New Body
p.x = 1.28943695621391310e+01
p.y = -1.51111514016986312e+01
p.z = -2.23307578892655734e-01
p.vx = 2.96460137564761618e-03 * DAYS_PER_YEAR
p.vy = 2.37847173959480950e-03 * DAYS_PER_YEAR
p.vz = -2.96589568540237556e-05 * DAYS_PER_YEAR
p.mass = 4.36624404335156298e-05 * SOLAR_MASS
return p
End
Static Public Sub Neptune() As Body
Dim P As New Body
p.x = 1.53796971148509165e+01
p.y = -2.59193146099879641e+01
p.z = 1.79258772950371181e-01
p.vx = 2.68067772490389322e-03 * DAYS_PER_YEAR
p.vy = 1.62824170038242295e-03 * DAYS_PER_YEAR
p.vz = -9.51592254519715870e-05 * DAYS_PER_YEAR
p.mass = 5.15138902046611451e-05 * SOLAR_MASS
return p
End
Static Public Sub Sun() As Body
Dim P As New Body
p.mass = SOLAR_MASS
return p
End
Public Sub OffsetMomentum(px As Float, py As Float, pz As Float) As Body
vx = -px / SOLAR_MASS
vy = -py / SOLAR_MASS
vz = -pz / SOLAR_MASS
Return Me
End
End Class
Class NBodySystem
Private Bodies As Body[]
Public Sub _new()
Dim PX, PY, PZ As Float
Dim I As Integer
Bodies = [ Body.Sun(), Body.Jupiter(), Body.Saturn(), Body.Uranus(), Body.Neptune() ]
For I = 0 To Bodies.Max
PX += Bodies[I].vx * Bodies[I].mass
PY += Bodies[I].vy * Bodies[I].mass
PZ += Bodies[I].vz * Bodies[I].mass
Next
Bodies[0].offsetMomentum(PX, PY, PZ)
End
Public Sub Advance(dt As Float)
Dim I, J As Integer
Dim iBody, jBody As Body
Dim dx, dy, dz As Float
Dim ix, iy, iz As Float
Dim dSquared, fMag As Float
Dim iMass, jMass, iMag, jMag As Float
For I = 0 To Bodies.Max
iBody = Bodies[I]
iMass = iBody.mass
ix = iBody.x
iy = iBody.y
iz = iBody.z
For J = I + 1 To Bodies.Max
jBody = Bodies[J]
jMass = jBody.mass
dx = ix - jBody.x
dy = iy - jBody.y
dz = iz - jBody.z
dSquared = dx * dx + dy * dy + dz * dz
fMag = dt / (dSquared * Sqr(dSquared))
iMag = iMass * fMag
jMag = jMass * fMag
iBody.vx -= dx * jMag
iBody.vy -= dy * jMag
iBody.vz -= dz * jMag
jBody.vx += dx * iMag
jBody.vy += dy * iMag
jBody.vz += dz * iMag
Next
Next
For I = 0 To Bodies.Max
iBody = Bodies[i]
iBody.x += dt * iBody.vx
iBody.y += dt * iBody.vy
iBody.z += dt * iBody.vz
Next
End
Public Sub Energy() As Float
Dim dx, dy, dz, distance, E As Float
Dim iBody, jBody As Body
Dim I, J As Integer
For I = 0 To Bodies.Max
iBody = bodies[i]
E += 0.5 * iBody.mass * (iBody.vx * iBody.vx + iBody.vy * iBody.vy + iBody.vz * iBody.vz)
For J = I + 1 To Bodies.Max
jBody = Bodies[J]
dx = iBody.x - jBody.x
dy = iBody.y - jBody.y
dz = iBody.z - jBody.z
distance = Sqr(dx*dx + dy*dy + dz*dz)
E -= (iBody.mass * jBody.mass) / distance
Next
Next
return E
End
End Class
Dim S As New NBodySystem
Dim I, N As Integer
For N = 1 To 5
Print S.Energy()
For I = 1 To 100000
S.Advance(0.01)
Next
Next
Print S.Energy()
Error CStr(Jit.Time)