Thursday, March 28, 2024

Three body problem JS implementation

My HTML JS implementation of three body problem simulation.

Use Verlet algorithm and initial condition that give interesting stable trajectory in 8 shape. 

Used as base for animations rendered for my channel here:

https://youtu.be/5DgYCBNfBDI


 


 <html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<canvas id="mycanvas" width="1280" height="1280"></canvas>



<script type="text/javascript">

var N = 3;
// F = 1/r^2
var fx = [];
var fy = [];
var x= [],vx= [],y= [],vy= [];
var xp1= [], yp1= [];
var xm1= [], ym1= [];

var W,H;
var dt = 0.015;
var m = 1;
var G = 1;//0.001;
var step;

var d;
// przygotowanie do rysowania
var canvas = document.getElementById('mycanvas');
W=800; H=800;
canvas.width = W;
canvas.height = H;
var ctx = canvas.getContext('2d');

// inicjalizacja
function init()
{
for(var i=0; i<N; i++)
{
// x[i]=xm1[i]=xp1[i]=0.5+(0.5)*(Math.random()-0.5);
// y[i]=ym1[i]=xm1[i]=0.5+(0.5)*(Math.random()-0.5);

vx[i] = vy[i] = 0;
}

x[0] = 0.5-0.2;
y[0] = 0.5-0.2;
x[1] = 0.5+0.2;
y[1] = 0.5-0.2;
x[2] = 0.5;
y[2] = 0.5+0.2;


    x[0] = 0.97000436; y[0] = -0.24308753;
    x[1] = -0.97000436;    y[1] = 0.24308753;
    x[2] = 0;    y[2] = 0;
    
    vx[0] = 0.93240737/2.0;
    vy[0] = 0.86473146/2.0;
    vx[1] = 0.93240737 / 2.0;
    vy[1] = 0.86473146 / 2.0;
    vx[2] = -0.93240737;
    vy[2] = -0.86473146;


step = 0;
}

function dist(x1,y1,x2,y2) { return Math.sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) ); }
// pętla obliczeniowa i rysująca
loop=function()
{
step++;

//rysowanie punktu
ctx.clearRect(0,0,W,H);
ctx.strokeStyle = "rgb(0,0,0)";

for(var i=0; i<N; i++)
{
fx[i] = 0;
fy[i] = 0;
}

// sum forces
for(var i=0; i<N; i++)
for(var j=i+1; j<N; j++)
{
// dij
    d = dist(x[i], y[i], x[j], y[j]);
    
    if(d != 0)
    {
        var rx = x[i] - x[j];
        var ry = y[i] - y[j];
        var rx = rx / d; // norm
        var ry = ry / d; // norm
        var Fx = rx * G * m*m / (d*d);
        var Fy = ry * G * m*m / (d*d);

        fx[i] -= Fx;
        fy[i] -= Fy;
        fx[j] += Fx;
        fy[j] += Fy;
    }
}

// integrate
if(step==1)
{
    for(var b=0; b<N; b++)
    {
        vx[b] = vx[b] + fx[b]/m*dt;
        vy[b] = vy[b] + fy[b]/m*dt;
        xp1[b] = x[b] + vx[b]*dt;
        yp1[b] = y[b] + vy[b]*dt;
    }
}
else
{
    // VERLET
    for(var b=0; b<N; b++)
    {
        xp1[b] = 2*x[b]-xm1[b]+dt*dt*fx[b]/m;
        yp1[b] = 2*y[b]-ym1[b]+dt*dt*fy[b]/m;
    }
}


for(var b=0; b<N; b++)
{
    xm1[b] = x[b];
    ym1[b] = y[b];
    x[b] = xp1[b];
    y[b] = yp1[b];
    vx[b] = (x[b] - xm1[b]) / (2*dt);
    vy[b] = (y[b] - ym1[b]) / (2*dt);
}

for(var i=0; i<N; i++)
{
    ctx.beginPath();
    ctx.arc(98*(x[i])+W/2,98*(y[i])+H/2,6,0,2*Math.PI); // kolko
    ctx.fill(); // rysuj
}

ctx.font = '48px serif';
  ctx.fillText(step.toString(), 10, 50);

//kontynuuj petle
requestAnimationFrame(loop);

};

// start
init();
loop();

  </script>

  <style type="text/css">
  canvas { border: 1px solid rgb(0,0,0); }
 </style>
<br>

</body>
</html>

 

 

 

Soda Constructor (Revisited)