|
N-Body dynamics
d 2ri / dt 2 = Fi = G m ∑ k (rk - ri ) / |rk - ri|3 for N = 4096 are simulated. We put G m = 1 by the time scaling. Explicit scheme r t+2 = 2 r t+1 - r t + F t+1 Δt2 with constant time step Δt is used. |
See also N = 8K simulation. I can't make a spiral galaxy (I'm not an expert :)
| N = | 4096 | 16K | 32K |
| HD 4870 | 1200=20×60 20 |
80=4×20 21.5 | 21=2.1×10 22.5 |
| HD 4650 | 420=21×20 7 |
28=14×2 7.5 | 5=2.5×2 5.4 |
HD 4870 800 shaders, 790gpu/1100mem MHz, 256 bit bus width,
GDDR5 memory
HD 4650 320 shaders, 712gpu/550mem MHz, 128 bit bus width, GDDR3 memory
Numbers: shaders power ratio is 800×790 / 320×712 = 2.8 and performance ratio is 20/7 = 2.9 so GDDR3 memory bandwidth is not a bottleneck in this simulation!
<script id="shader-fs" type="x-shader/x-fragment">
precision highp float;
uniform sampler2D samp;
uniform sampler2D samp1;
varying vec2 vTexCoord;
const float d = 1./64., e2 = .01, dt2 = .00001;
void main(void) {
vec3 r = texture2D(samp, vTexCoord).xyz;
vec3 r1 = texture2D(samp1, vTexCoord).xyz;
vec3 f = vec3( 0. );
for(float y = 0.; y < 1.; y += d ){
for(float x = 0.; x < 1.; x += d ){
vec3 v = texture2D(samp1, vTexCoord + vec2(x, y)).xyz - r1;
float a = dot(v, v) + e2;
f += v/(a*sqrt(a));
}
}
r = 2.*r1 - r + f*dt2;
gl_FragColor = vec4(r, 0. );
}
</script>
This vertex script renders the 2×2 square into FBO
to make computations for every pixel in textures.
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec2 aPos;
attribute vec2 aTexCoord;
varying vec2 vTexCoord;
void main(void) {
gl_Position = vec4(aPos, 0., 1.);
vTexCoord = aTexCoord;
}
</script>
N points square lattice is used to show the bodies in the shader below
<script id="shader-vs-show" type="x-shader/x-vertex">
attribute vec2 aPoints;
uniform mat4 mvMatrix;
uniform mat4 prMatrix;
uniform sampler2D uTexSamp;
varying vec4 color;
void main(void) {
gl_Position = prMatrix * mvMatrix * texture2D(uTexSamp, aPoints );
color = vec4( 1.);
}
</script>
Computations are organized by the function
function draw(){
gl.viewport(0, 0, 64, 64);
gl.useProgram(prog);
for(var i = 0; i < it; i++){
gl.uniform1i(sampLoc, 0);
gl.uniform1i(samp1Loc, 1);
gl.bindFramebuffer(gl.FRAMEBUFFER, FBO2);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
gl.uniform1i(sampLoc, 1);
gl.uniform1i(samp1Loc, 2);
gl.bindFramebuffer(gl.FRAMEBUFFER, FBO);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
gl.uniform1i(sampLoc, 2);
gl.uniform1i(samp1Loc, 0);
gl.bindFramebuffer(gl.FRAMEBUFFER, FBO1);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}
drawScene();
frames++;
}
at last drawScene() prepares transformations and executes
gl.drawArrays(gl.POINTS, 0, 64*64);to show scene.
[1]
GPU Gems 3. Chapter 31. Fast N-Body Simulation with CUDA
L.Nyland, M.Harris, J.Prins
[2] Kazuki Fujiwara, Naohito Nakasato
Fast Simulations of Gravitational Many-body Problem on RV770 GPU
arXiv:0904.3659v1
[3] S.F.P.Zwart, R.G.Belleman, P.M.Geldof
High-performance direct gravitational N-body simulations
on graphics processing units. New Astronomy 12 (2007) 641-650
[4]
Vanderbei's N-Body Page 1000 "Star Clusters" Java simulation
[5] WebGL Orrery by Ilmari Heikkinen