diff options
author | navanchauhan <navanchauhan@gmail.com> | 2023-05-01 00:29:15 -0600 |
---|---|---|
committer | navanchauhan <navanchauhan@gmail.com> | 2023-05-01 00:29:15 -0600 |
commit | 505a7d7ac9fb34cea98fb54d8d56be54fdc79a13 (patch) | |
tree | c93c1a8d494e70c021dfc8e3a6909e7ca000badf | |
parent | ade0b1ea232e4731f7ce3a0122139a92319890ef (diff) |
add slider for num bodies
-rw-r--r-- | Content/posts/2023-04-30-n-body-simulation.md | 691 | ||||
-rw-r--r-- | docs/assets/n-body/script.js | 598 | ||||
-rw-r--r-- | docs/feed.rss | 690 | ||||
-rw-r--r-- | docs/posts/2023-04-30-n-body-simulation.html | 686 |
4 files changed, 2663 insertions, 2 deletions
diff --git a/Content/posts/2023-04-30-n-body-simulation.md b/Content/posts/2023-04-30-n-body-simulation.md index 4f64f4c..52f38da 100644 --- a/Content/posts/2023-04-30-n-body-simulation.md +++ b/Content/posts/2023-04-30-n-body-simulation.md @@ -7,6 +7,697 @@ tags: astrophysics, mathematics # n-body solution generator This post requires JavaScript to be viewed properly :( + +Adapted from the Numerics Tutorial - [kirklong/ThreeBodyBot](https://github.com/kirklong/ThreeBodyBot/tree/master/NumericsTutorial). The Julia code has been rewritten in JavaScript. + +Workflow: + +* Understand the problem + +* Visualise a basic orbit + +* Solve and plot the classic figure-8 orbit + +* random n-body solution generator + +**To workaround memory issues, the simulations are only run on-demand when the user clicks the respective button. Scroll down to the bottom of the page to see the results.** + +## The n-body problem + +The n-body problem is a classic puzzle in physics (and thus astrophysics) and mathematics that deals with predicting the motion of multiple celestial objects that interact with each other through gravitational forces. + +Imagine you are observing a *cosmic dance* between multiple celestial bodies, all tugging on one another as they move through space. The n-body problem aims to undersand and predict the paths of these objects as they move through space. + +When `n=2`, i.e we have only two objects, say the Earth and the Moon, we can easily apply Newtonian physics to predict their motion. However, when `n>2`, the problem becomes much more difficult to solve analytically. This is because each object feels the gravitational pull from all other objects, and thus the equations of motion become coupled and non-linear. + +As the number of objects increases, finding an exact solution becomes impossible, and we rely on analyticals approximations. + +## Visualising a basic orbit + +If we want to create a n-body simulation in our browser, we need to figure out how we are going to visualise the motion of the objects. There are a few ways to do this, but the easiest is to use Plotly.js, a JavaScript library for creating interactive graphs. (An alternative is to use the HTML5 canvas element). + +```javascript +/* + * Earth - Sun Orbit Plot + * Taken from Numerics tutorial + */ + +const G = 6.67e-11; +const Msun = 2e30; +const AU = 1.5e11; +const v0 = Math.sqrt(G * Msun / AU); // SI + +function dR(r, v) { + const dv = [-G * Msun / Math.pow(r[0] ** 2 + r[1] ** 2, 3 / 2) * r[0], -G * Msun / Math.pow(r[0] ** 2 + r[1] ** 2, 3 / 2) * r[1]]; + const dr = [...v]; + return [dr, dv]; +} + +// initialize system +let r = [-AU, 0]; +const theta = Math.atan2(r[1], r[0]); +let v = [-v0 * Math.sin(theta), v0 * Math.cos(theta)]; + +const t = Array.from({ length: 1001 }, (_, i) => i / 100 + 0.0); // years +const yearSec = 365 * 24 * 3600; +const dt = (t[1] - t[0]) * yearSec; // s +const x4Plot = Array.from({ length: t.length }, () => 0); +const y4Plot = Array.from({ length: t.length }, () => 0); + +// integrate using RK4! +for (let i = 0; i < t.length; i++) { + const k1 = dR(r, v).map(x => x.map(y => y * dt)); + const k2 = dR(r.map((ri, j) => ri + k1[0][j] / 2), v.map((vi, j) => vi + k1[1][j] / 2)).map(x => x.map(y => y * dt)); + const k3 = dR(r.map((ri, j) => ri + k2[0][j] / 2), v.map((vi, j) => vi + k2[1][j] / 2)).map(x => x.map(y => y * dt)); + const k4 = dR(r.map((ri, j) => ri + k3[0][j]), v.map((vi, j) => vi + k3[1][j])).map(x => x.map(y => y * dt)); + r = r.map((ri, j) => ri + (k1[0][j] + 2 * k2[0][j] + 2 * k3[0][j] + k4[0][j]) / 6); + v = v.map((vi, j) => vi + (k1[1][j] + 2 * k2[1][j] + 2 * k3[1][j] + k4[1][j]) / 6); + x4Plot[i] = r[0]; + y4Plot[i] = r[1]; +} + +// make data for plot +var sun = { x: 0, y: 0 }; +const earth = { x: x4Plot.map(x => x / AU), y: y4Plot.map(y => y / AU) }; +const circle = { x: Array.from({ length: 1001 }, (_, i) => Math.cos(i / 100 * 2 * Math.PI)), y: Array.from({ length: 1001 }, (_, i) => Math.sin(i / 100 * 2 * Math.PI)) }; +``` + + +This code simulates the orbit of Earth around the Sun, using a numerical method called the Runge-Kutta 4th order (RK4) method. + +First, we define some constants: + +G: the gravitational constant (6.67e-11 N m²/kg²) +Msun: the mass of the Sun (2e30 kg) +AU: an astronomical unit, the average distance between Earth and Sun (1.5e11 m) +v0: the initial velocity of Earth, calculated from its distance to the Sun +Next, the function dR takes the position r and velocity v of Earth as input and returns the rate of change in position (dr) and the rate of change in velocity (dv) using the gravitational force formula. + +We then initialize the position r and velocity v of Earth, and create an array t that represents time in years, divided into 1001 steps. We also define yearSec as the number of seconds in a year and dt as the time step in seconds. + +Now, we integrate the Earth's motion using the RK4 method. For each time step, we calculate the rates of change for position and velocity (k1, k2, k3, k4) and update Earth's position and velocity based on these. We store the updated position in x4Plot and y4Plot. + +Finally, we normalize the position data by dividing it by the astronomical unit (AU) to make it more visually meaningful. We also create a circle for reference, which represents a perfect circular orbit. The code ends with the data for the Sun's position, Earth's orbit, and the reference circle ready to be plotted. + +### Plotting the orbit + +Now that we have the data for the Sun's position, Earth's orbit, and the reference circle, we can plot them using Plotly.js. + +```javascript + let traceSun = { + x: [sun.x], + y: [sun.y], + mode: "markers", + marker: { + symbol: "star", + size: 10, + color: "gold", + }, + name: "Sun", + }; + + const traceEarth = { + x: earth.x, + y: earth.y, + mode: "lines", + line: { + color: "white" + }, + name: "Earth", + }; + + const traceOrbit = { + x: circle.x, + y:circle.y, + mode: "lines", + line: { + color: "crimson", + dash: "dash" + }, + name: "1 AU Circle", + }; + + const earthSunLayout = { + title: "Earth-Sun Orbit", + xaxis: { + title: "x [AU]", + range: [-1.1,1.1], + showgrid: true, + gridcolor: "rgba(255,255,255,0.5)", + gridwidth: 1, + zeroline: true, + tickmode: "auto", + nticks: 5, + }, + yaxis: { + title: "y [AU]", + range: [-1.1,1.1], + showgrid: true, + gridcolor: "rgba(255,255,255,0.5)", + gridwidth: 1, + zeroline: false, + tickmode: "auto", + nticks: 5, + }, + margin: { + l: 50, + r: 50, + b: 50, + t: 50, + pad: 4, + }, + paper_bgcolor: "black", + plot_bgcolor: "black", + }; + Plotly.newPlot("plot",[traceSun,traceEarth,traceOrbit], earthSunLayout); +``` + +## Figure of 8 orbit + + +The figure of 8 solution in the three-body problem refers to a unique and special trajectory where three celestial bodies (e.g., planets, stars) move in a figure of 8 shaped pattern around their mutual center of mass. This is special because it represents a stable and periodic solution to the three-body problem, which is known for its complexity and lack of general solutions. + +In the figure of 8 solution, each of the three bodies follows the same looping path, but with a phase difference such that when one body is at one end of the loop, the other two are symmetrically positioned elsewhere along the path. The bodies maintain equal distances from each other throughout their motion, and their velocities and positions are perfectly balanced to maintain this periodic motion. + +The figure of 8 is interesting because: + +* It is a relatively stable solution, which means that the objects continue to follow the same looping path almost indefinitely. + +* It breaks down the notion that no simple periodic solutions exist for the three-body problem. + +* It looks cool! + +### Show me the code + +The code for this simulation is very similar to the Earth-Sun orbit simulation, except that we now have three bodies instead of two. We also use a different set of initial conditions to generate the figure of 8 orbit. + +```javascript + +function deltaR(coords, masses, nBodies, G) { + let x = coords[0]; + let y = coords[1]; + let vx = coords[2]; + let vy = coords[3]; + + let delta = math.clone(coords); + + for (let n = 0; n < nBodies; n++) { + let xn = x[n]; + let yn = y[n]; + let deltaVx = 0.0; + let deltaVy = 0.0; + + for (let i = 0; i < nBodies; i++) { + if (i !== n) { + let sep = Math.sqrt(Math.pow(xn - x[i], 2) + Math.pow(yn - y[i], 2)); // Euclidean distance + deltaVx -= G * masses[i] * (xn - x[i]) / Math.pow(sep, 3); + deltaVy -= G * masses[i] * (yn - y[i]) / Math.pow(sep, 3); + } + } + + delta[2][n] = deltaVx; + delta[3][n] = deltaVy; + } + + delta[0] = vx; + delta[1] = vy; + + return delta; +} + +function step(coords, masses, deltaT, nBodies = 3, G = 6.67408313131313e-11) { + let k1 = math.multiply(deltaT, deltaR(coords, masses, nBodies, G)); + let k2 = math.multiply(deltaT, deltaR(math.add(coords, math.multiply(k1, 0.5)), masses, nBodies, G)); + let k3 = math.multiply(deltaT, deltaR(math.add(coords, math.multiply(k2, 0.5)), masses, nBodies, G)); + let k4 = math.multiply(deltaT, deltaR(math.add(coords, k3), masses, nBodies, G)); + + coords = math.add(coords, math.multiply(math.add(k1, math.multiply(2.0, k2), math.multiply(2.0, k3), k4), 1/6)); + + return coords; +} + + // Initial conditions setup + let M = [1, 1, 1]; + let x = [-0.97000436, 0.0, 0.97000436]; + let y = [0.24208753, 0.0, -0.24208753]; + let vx = [0.4662036850, -0.933240737, 0.4662036850]; + let vy = [0.4323657300, -0.86473146, 0.4323657300]; + let Ei = -1 / Math.sqrt(Math.pow(2 * 0.97000436, 2) + Math.pow(2 * 0.24208753, 2)) - 2 / Math.sqrt(Math.pow(0.97000436, 2) + Math.pow(0.24208753, 2)) + 0.5 * (math.sum(math.add(math.dotPow(vx, 2), math.dotPow(vy, 2)))); + + function linspace(start, stop, num) { + const step = (stop - start) / (num - 1); + return Array.from({length: num}, (_, i) => start + (step * i)); + } + + let coords = [x, y, vx, vy]; + const time = linspace(0, 6.3259, 1001); + let deltaT = time[1] - time[0]; + + let X = math.zeros(3, time.length).toArray(); + let Y = math.zeros(3, time.length).toArray(); + let VX = math.zeros(3, time.length).toArray(); + let VY = math.zeros(3, time.length).toArray(); + + for (let i = 0; i < time.length; i++) { + coords = step(coords, M, deltaT, 3, 1); + X.forEach((_, idx) => X[idx][i] = coords[0][idx]); + Y.forEach((_, idx) => Y[idx][i] = coords[1][idx]); + VX.forEach((_, idx) => VX[idx][i] = coords[2][idx]); + VY.forEach((_, idx) => VY[idx][i] = coords[3][idx]); + } +``` + +The `deltaR` function computes the rate of change in position and velocity of the celestial bodies based on their current positions, velocities, and masses. It accounts for the gravitational forces between all bodies. + +The `step` function performs a single RK4 integration step, updating the positions and velocities of the celestial bodies. It uses `deltaR` to compute the four increments (k1, k2, k3, and k4) and then updates the coordinates accordingly. + +Next, the initial conditions for the figure-8 three-body problem are set. The masses (`M`), initial positions (`x`, `y`), and initial velocities (`vx`, `vy`) are provided. `Ei` calculates the initial total energy of the system. + +The `linspace` function is defined to create a linearly spaced array of time points. `coords` is an array containing the positions and velocities for all bodies. The `time` array is created using `linspace`, and `deltaT` is set as the time step. + +`X`, `Y`, `VX`, and `VY` are 2D arrays that will store the positions and velocities of the celestial bodies over time. They are initialized with zeros and will be updated in the loop. + +Finally, a loop iterates over each time step, updating the positions and velocities of the celestial bodies using the `step` function. The updated coordinates are stored in the `X`, `Y`, `VX`, and `VY` arrays. + +### Animation? + +Now that we have time-series data, we need to animate it. We can use Plotly's animate function, as this does not force a full re-render, saving us some precious GPU and CPU cycles when we are trying to run this in the browser itself + +```javascript + function plotClassicFunc() { + var tailLength = 1; + if (plotIndex < tailLength) { + tailLength = 0; + } else if (plotIndex > time.length) { + plotIndex = 0; + } else { + tailLength = plotIndex - tailLength; + } + + var currentIndex = plotIndex; + + try { + time[currentIndex].toFixed(3); + } catch (e) { + currentIndex = 0; + } + + const data = [ + { + x: X[0].slice(tailLength, currentIndex), + y: Y[0].slice(tailLength, currentIndex), + mode: 'lines+markers', + marker: { + symbol: 'star', + size: 8, + line: { width: 0 }, + }, + line: { + width: 2, + }, + name: '', + }, + { + x: X[1].slice(tailLength, currentIndex), + y: Y[1].slice(tailLength, currentIndex), + mode: 'lines+markers', + marker: { + symbol: 'star', + size: 8, + line: { width: 0 }, + }, + line: { + width: 2, + }, + name: '', + }, + { + x: X[2].slice(tailLength, currentIndex), + y: Y[2].slice(tailLength, currentIndex), + mode: 'lines+markers', + marker: { + symbol: 'star', + size: 8, + line: { width: 0 }, + }, + line: { + width: 2, + }, + name: '', + }, + ]; + + // width: 1000, height: 400 + const layout = { + title: '∞ Three-Body Problem: t = ' + time[currentIndex].toFixed(3), + xaxis: { + title: 'x', + range: [-1.1,1.1] + }, + yaxis: { + title: 'y', + scaleanchor: 'x', + scaleratio: 1, + range: [-0.5,0.5] + }, + plot_bgcolor: 'black', + paper_bgcolor: 'black', + font: { + color: 'white', + }, + }; + + try { + Plotly.animate("plot", { + data: data, layout: layout + }, { + staticPlot: true, + transition: { + duration: 0, + }, + frame: { + duration: 0, + redraw: false, + } + }); + } catch (err) { + Plotly.newPlot('plot', data, layout); + } + + + plotIndex += delay; + if (plotClassic===true) { + try { + requestAnimationFrame(plotClassicFunc); + } + catch (err) { + console.log(err) + } + } + + } +``` + +## "General" N-Body Solver + + + +### Show me the code! + +```javascript + +function step(coords, masses, deltaT, nBodies = 3, G = 6.67408313131313e-11) { + let k1 = math.multiply(deltaT, deltaR(coords, masses, nBodies, G)); + let k2 = math.multiply(deltaT, deltaR(math.add(coords, math.multiply(k1, 0.5)), masses, nBodies, G)); + let k3 = math.multiply(deltaT, deltaR(math.add(coords, math.multiply(k2, 0.5)), masses, nBodies, G)); + let k4 = math.multiply(deltaT, deltaR(math.add(coords, k3), masses, nBodies, G)); + + coords = math.add(coords, math.multiply(math.add(k1, math.multiply(2.0, k2), math.multiply(2.0, k3), k4), 1/6)); + + return coords; +} + +function detectCollisionsEscape(coords, deltaT, maxSep) { + const [x, y, vx, vy] = coords; + const V = vx.map((v, i) => Math.sqrt(v ** 2 + vy[i] ** 2)); + const R = V.map(v => v * deltaT); + let collision = false, collisionInds = null, escape = false, escapeInd = null; + + for (let n = 0; n < x.length; n++) { + const rn = R[n], xn = x[n], yn = y[n]; + for (let i = 0; i < x.length; i++) { + if (i !== n) { + const minSep = rn + R[i]; + const sep = Math.sqrt((xn - x[i]) ** 2 + (yn - y[i]) ** 2); + if (sep < minSep) { + collision = true; + collisionInds = [n, i]; + } else if (sep > maxSep) { + escape = true; + escapeInd = n; + return [collision, collisionInds, escape, escapeInd]; + } + } + } + } + return [collision, collisionInds, escape, escapeInd]; +} + +function nBodyStep(coords, masses, deltaT, maxSep, nBodies, G = 6.67408313131313e-11) { // Similar to our step function before, but keeping track of collisions + coords = step(coords, masses, deltaT, nBodies, G); // Update the positions as we did before + //console.log(detectCollisionsEscape(coords, deltaT, maxSep)); + let [collision, collisionInds, escape, escapeInd] = detectCollisionsEscape(coords, deltaT, maxSep); // Detect collisions/escapes + + + if (collision) { // Do inelastic collision and delete extra body (2 -> 1) + const [i1, i2] = collisionInds; + const [x1, x2] = [coords[0][i1], coords[0][i2]]; + const [y1, y2] = [coords[1][i1], coords[1][i2]]; + const [vx1, vx2] = [coords[2][i1], coords[2][i2]]; + const [vy1, vy2] = [coords[3][i1], coords[3][i2]]; + const [px1, px2] = [masses[i1] * vx1, masses[i2] * vx2]; + const [py1, py2] = [masses[i1] * vy1, masses[i2] * vy2]; + const px = px1 + px2; + const py = py1 + py2; + const newM = masses[i1] + masses[i2]; + const vfx = px / newM; + const vfy = py / newM; + coords[0][i1] = (x1 * masses[i1] + x2 * masses[i2]) / (masses[i1] + masses[i2]); // Center of mass + coords[1][i1] = (y1 * masses[i1] + y2 * masses[i2]) / (masses[i1] + masses[i2]); + coords[2][i1] = vfx; + coords[3][i1] = vfy; + coords[0].splice(i2, 1); + coords[1].splice(i2, 1); + coords[2].splice(i2, 1); + coords[3].splice(i2, 1); + masses[i1] = newM; + masses.splice(i2, 1); + nBodies--; + } + // Could also implement condition for escape where we stop calculating forces but I'm too lazy for now + return [coords, masses, nBodies, collision, collisionInds, escape, escapeInd]; +} + +function uniform(min, max) { + return Math.random() * (max - min) + min; +} + +function deepCopyCoordsArray(arr) { + return arr.map(innerArr => innerArr.slice()); +} + +function genNBodyResults(nBodies, tStop, nTPts, nBodiesStop = 10, G = 6.67408313131313e-11) { + + var btn = document.getElementById("startSim3"); + // Set button text to Solving + var prevText = btn.innerHTML; + btn.innerHTML = "Solving..."; + + let coords = [Array(nBodies).fill(0), Array(nBodies).fill(0), Array(nBodies).fill(0), Array(nBodies).fill(0)]; + const Mstar = 2e30; + const Mp = Mstar / 1e4; + + for (let i = 0; i < nBodies; i++) { // Initialize coordinates on ~Keplerian orbits + let accept = false; + let r = null; + while (!accept) { // Prevent a particle from spawning within 0.2 AU too close to "star" + r = Math.random() * 2 * 1.5e11; // Say radius of 2 AU + if (r / 1.5e11 > 0.2) { + accept = true; + } + } + const theta = uniform(0, 2 * Math.PI); + const x = r * Math.cos(theta); + const y = r * Math.sin(theta); + const v = Math.sqrt(G * Mstar / r); + const perturbedV = v + v / 1000 * uniform(-1, 1); // Perturb the velocities ever so slightly + const vTheta = Math.atan2(y, x); + coords[0][i] = x; + coords[1][i] = y; + coords[2][i] = -perturbedV * Math.sin(vTheta); + coords[3][i] = perturbedV * Math.cos(vTheta); + } + + //console.log('Initial coords:', coords); + + + let masses = Array(nBodies).fill(Mp); // Initialize masses + masses[0] = Mstar; // Make index one special as the central star + coords[0][0] = 0; + coords[1][0] = 0; + coords[2][0] = 0; + coords[3][0] = 0; // Initialize central star at origin with no velocity + const yearSec = 365 * 24 * 3600; + const time = Array.from({ length: nTPts }, (_, i) => i * tStop / (nTPts - 1) * yearSec); // Years -> s + let t = time[0]; + const deltaT = time[1] - time[0]; + let tInd = 0; + const coordsRecord = [deepCopyCoordsArray(coords)]; + const massRecord = [masses.slice()]; // Initialize records with initial conditions + + + while (tInd < nTPts && nBodies > nBodiesStop) { + //console.log('Initial coords:', coords); + [coords, masses, nBodies] = nBodyStep(coords, masses, deltaT, 10 * 1.5e11, nBodies, G); // Update + coordsRecord.push(deepCopyCoordsArray(coords)); + massRecord.push(masses.slice()); // Add to records + tInd++; + t = time[tInd]; + //console.log(`currently at t = ${(t / yearSec).toFixed(2)} years\r`); + } + console.log(`final time = ${time[tInd] / yearSec} years with ${nBodies} bodies remaining`); + + // Set button text to Start Simulation + btn.innerHTML = prevText; + + return [coordsRecord, massRecord, time.slice(0, tInd + 1)]; +} + + + var [coordsRecordR, _, tR] = genNBodyResults(256,1,1001); + //console.log(coordsRecordR); + const yearSec = 365 * 24 * 3600; + + function createFrame(coordsR) { + if (!coordsR || !coordsR[0] || !coordsR[1]) { + return []; + } + + const traceCentralStar = { + x: [coordsR[0][0] / 1.5e11], + y: [coordsR[1][0] / 1.5e11], + mode: 'markers', + type: 'scatter', + name: 'Central star', + marker: { color: 'gold', symbol: 'star', size: 10 }, + }; + + const xCoords = coordsR[0].slice(1).map(x => x / 1.5e11); + const yCoords = coordsR[1].slice(1).map(y => y / 1.5e11); + + const traceOtherBodies = { + x: xCoords, + y: yCoords, + mode: 'markers', + type: 'scatter', + name: '', + marker: { color: 'dodgerblue', symbol: 'circle', size: 2 }, + }; + + return [traceCentralStar, traceOtherBodies]; + } + + + function createLayout(i) { + return { + title: { + text: `N-Body Problem: t = ${Number(t[i] / yearSec).toFixed(3)} years`, + x: 0.03, + y: 0.97, + xanchor: 'left', + yanchor: 'top', + font: { size: 14 }, + }, + xaxis: { title: 'x [AU]', range: [-2.1, 2.1] }, + yaxis: { title: 'y [AU]', range: [-2.1, 2.1], scaleanchor: 'x', scaleratio: 1 }, + showlegend: false, + margin: { l: 60, r: 40, t: 40, b: 40 }, + width: 800, + height: 800, + plot_bgcolor: 'black', + }; +} + + function animateNBodyProblem() { + const nFrames = tR.length; + + for (let i = 0; i < nFrames; i++) { + const frameData = createFrame(coordsRecordR[i]); + const layout = createLayout(i); + //Plotly.newPlot(plotDiv, frameData, layout); + try { + Plotly.animate("plot", { + data: frameData, layout: layout + }, { + staticPlot: true, + transition: { + duration: 0, + }, + frame: { + duration: 0, + redraw: false, + } + }); + } catch (err) { + Plotly.newPlot('plot', frameData, layout); + } + } +} + +animateNBodyProblem(); +``` + +## Playground + +<script src="https://cdn.plot.ly/plotly-latest.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/11.8.0/math.js"></script> +<script src="/assets/n-body/script.js"></script> +<div id="main-plot-div"> +<div id="plot"></div> + +<label for="speedControl">Speed for 3-Body Visualisation</label> +<input type="range" min="1" max="20" value="10" id="speedControl"> +<label for="nBodies">Number of Bodies for n-Body Simulation (5-500)</label> +<input type="range" min="5" max="500" value="256" id="nBodies"> +</div> +<button type="button" id="startSim1" onclick="plotEarthSun()">Sun-Earth Orbit</button> +<button type="button" id="startSim2" onclick="plotClassic3BodyProblem()">Classic 3-Body Problem</button> +<button type="button" id="startSim3" onclick="plotRandom3BodySimulation()">Random n-Body Simulation</button> +<script> +function clearAl() { + plotOrbit = false; + plotClassic = false; + plotRandom = false; +} + +function plotEarthSun() { + clearAl(); + plotOrbit = true; + calculateAndPlot(); + setTimeout(function(){ + calculateAndPlot() + }, 500); + } + +function plotClassic3BodyProblem() { + clearAl(); + plotClassic = true; + calculateAndPlot(); + setTimeout(function(){ + calculateAndPlot() + }, 500); + } + +function plotRandom3BodySimulation() { + clearAl(); + plotRandom = true; + calculateAndPlot(); + } + + +</script> + +<script> + document.getElementById("speedControl").addEventListener("input", (event) => { + const speedPercentage = parseInt(event.target.value, 10); + delay = speedPercentage; // Adjust the delay based on the trackbar value +}); + document.getElementById("nBodies").addEventListener("input", (event) => { + nBodies = parseInt(event.target.value, 10); + }); + + </script> + <noscript> This post requires JavaScript to be viewed properly :( </noscript> diff --git a/docs/assets/n-body/script.js b/docs/assets/n-body/script.js new file mode 100644 index 0000000..e87d92c --- /dev/null +++ b/docs/assets/n-body/script.js @@ -0,0 +1,598 @@ +// Global variables +var plotOrbit = true +var plotClassic = false +var plotRandom = false +var plotIndex = 0 +var delay = 10 +var tailLength = 1; +var nBodies = 256; + +/* + * Earth - Sun Orbit Plot + * Taken from Numerics tutorial + */ + +const G = 6.67e-11; +const Msun = 2e30; +const AU = 1.5e11; +const v0 = Math.sqrt(G * Msun / AU); // SI + +function dR(r, v) { + const dv = [-G * Msun / Math.pow(r[0] ** 2 + r[1] ** 2, 3 / 2) * r[0], -G * Msun / Math.pow(r[0] ** 2 + r[1] ** 2, 3 / 2) * r[1]]; + const dr = [...v]; + return [dr, dv]; +} + +// initialize system +let r = [-AU, 0]; +const theta = Math.atan2(r[1], r[0]); +let v = [-v0 * Math.sin(theta), v0 * Math.cos(theta)]; + +const t = Array.from({ length: 1001 }, (_, i) => i / 100 + 0.0); // years +const yearSec = 365 * 24 * 3600; +const dt = (t[1] - t[0]) * yearSec; // s +const x4Plot = Array.from({ length: t.length }, () => 0); +const y4Plot = Array.from({ length: t.length }, () => 0); + +// integrate using RK4! +for (let i = 0; i < t.length; i++) { + const k1 = dR(r, v).map(x => x.map(y => y * dt)); + const k2 = dR(r.map((ri, j) => ri + k1[0][j] / 2), v.map((vi, j) => vi + k1[1][j] / 2)).map(x => x.map(y => y * dt)); + const k3 = dR(r.map((ri, j) => ri + k2[0][j] / 2), v.map((vi, j) => vi + k2[1][j] / 2)).map(x => x.map(y => y * dt)); + const k4 = dR(r.map((ri, j) => ri + k3[0][j]), v.map((vi, j) => vi + k3[1][j])).map(x => x.map(y => y * dt)); + r = r.map((ri, j) => ri + (k1[0][j] + 2 * k2[0][j] + 2 * k3[0][j] + k4[0][j]) / 6); + v = v.map((vi, j) => vi + (k1[1][j] + 2 * k2[1][j] + 2 * k3[1][j] + k4[1][j]) / 6); + x4Plot[i] = r[0]; + y4Plot[i] = r[1]; +} + +// make data for plot +var sun = { x: 0, y: 0 }; +const earth = { x: x4Plot.map(x => x / AU), y: y4Plot.map(y => y / AU) }; +const circle = { x: Array.from({ length: 1001 }, (_, i) => Math.cos(i / 100 * 2 * Math.PI)), y: Array.from({ length: 1001 }, (_, i) => Math.sin(i / 100 * 2 * Math.PI)) }; + +/* + * Generic Functions + * + * + */ + +function deltaR(coords, masses, nBodies, G) { + let x = coords[0]; + let y = coords[1]; + let vx = coords[2]; + let vy = coords[3]; + + let delta = math.clone(coords); + + for (let n = 0; n < nBodies; n++) { + let xn = x[n]; + let yn = y[n]; + let deltaVx = 0.0; + let deltaVy = 0.0; + + for (let i = 0; i < nBodies; i++) { + if (i !== n) { + let sep = Math.sqrt(Math.pow(xn - x[i], 2) + Math.pow(yn - y[i], 2)); // Euclidean distance + deltaVx -= G * masses[i] * (xn - x[i]) / Math.pow(sep, 3); + deltaVy -= G * masses[i] * (yn - y[i]) / Math.pow(sep, 3); + } + } + + delta[2][n] = deltaVx; + delta[3][n] = deltaVy; + } + + delta[0] = vx; + delta[1] = vy; + + return delta; +} + +function detectCollisionsEscape(coords, deltaT, maxSep) { + const [x, y, vx, vy] = coords; + const V = vx.map((v, i) => Math.sqrt(v ** 2 + vy[i] ** 2)); + const R = V.map(v => v * deltaT); + let collision = false, collisionInds = null, escape = false, escapeInd = null; + + for (let n = 0; n < x.length; n++) { + const rn = R[n], xn = x[n], yn = y[n]; + for (let i = 0; i < x.length; i++) { + if (i !== n) { + const minSep = rn + R[i]; + const sep = Math.sqrt((xn - x[i]) ** 2 + (yn - y[i]) ** 2); + if (sep < minSep) { + collision = true; + collisionInds = [n, i]; + } else if (sep > maxSep) { + escape = true; + escapeInd = n; + return [collision, collisionInds, escape, escapeInd]; + } + } + } + } + return [collision, collisionInds, escape, escapeInd]; +} + + + +function step(coords, masses, deltaT, nBodies = 3, G = 6.67408313131313e-11) { + let k1 = math.multiply(deltaT, deltaR(coords, masses, nBodies, G)); + let k2 = math.multiply(deltaT, deltaR(math.add(coords, math.multiply(k1, 0.5)), masses, nBodies, G)); + let k3 = math.multiply(deltaT, deltaR(math.add(coords, math.multiply(k2, 0.5)), masses, nBodies, G)); + let k4 = math.multiply(deltaT, deltaR(math.add(coords, k3), masses, nBodies, G)); + + coords = math.add(coords, math.multiply(math.add(k1, math.multiply(2.0, k2), math.multiply(2.0, k3), k4), 1/6)); + + return coords; +} + +function nBodyStep(coords, masses, deltaT, maxSep, nBodies, G = 6.67408313131313e-11) { // Similar to our step function before, but keeping track of collisions + coords = step(coords, masses, deltaT, nBodies, G); // Update the positions as we did before + //console.log(detectCollisionsEscape(coords, deltaT, maxSep)); + let [collision, collisionInds, escape, escapeInd] = detectCollisionsEscape(coords, deltaT, maxSep); // Detect collisions/escapes + + + if (collision) { // Do inelastic collision and delete extra body (2 -> 1) + const [i1, i2] = collisionInds; + const [x1, x2] = [coords[0][i1], coords[0][i2]]; + const [y1, y2] = [coords[1][i1], coords[1][i2]]; + const [vx1, vx2] = [coords[2][i1], coords[2][i2]]; + const [vy1, vy2] = [coords[3][i1], coords[3][i2]]; + const [px1, px2] = [masses[i1] * vx1, masses[i2] * vx2]; + const [py1, py2] = [masses[i1] * vy1, masses[i2] * vy2]; + const px = px1 + px2; + const py = py1 + py2; + const newM = masses[i1] + masses[i2]; + const vfx = px / newM; + const vfy = py / newM; + coords[0][i1] = (x1 * masses[i1] + x2 * masses[i2]) / (masses[i1] + masses[i2]); // Center of mass + coords[1][i1] = (y1 * masses[i1] + y2 * masses[i2]) / (masses[i1] + masses[i2]); + coords[2][i1] = vfx; + coords[3][i1] = vfy; + coords[0].splice(i2, 1); + coords[1].splice(i2, 1); + coords[2].splice(i2, 1); + coords[3].splice(i2, 1); + masses[i1] = newM; + masses.splice(i2, 1); + nBodies--; + } + // Could also implement condition for escape where we stop calculating forces but I'm too lazy for now + return [coords, masses, nBodies, collision, collisionInds, escape, escapeInd]; +} + +function uniform(min, max) { + return Math.random() * (max - min) + min; +} + +function deepCopyCoordsArray(arr) { + return arr.map(innerArr => innerArr.slice()); +} + +function genNBodyResults(nBodies, tStop, nTPts, nBodiesStop = 10, G = 6.67408313131313e-11) { + + var btn = document.getElementById("startSim3"); + // Set button text to Solving + var prevText = btn.innerHTML; + btn.innerHTML = "Solving..."; + + let coords = [Array(nBodies).fill(0), Array(nBodies).fill(0), Array(nBodies).fill(0), Array(nBodies).fill(0)]; + const Mstar = 2e30; + const Mp = Mstar / 1e4; + + for (let i = 0; i < nBodies; i++) { // Initialize coordinates on ~Keplerian orbits + let accept = false; + let r = null; + while (!accept) { // Prevent a particle from spawning within 0.2 AU too close to "star" + r = Math.random() * 2 * 1.5e11; // Say radius of 2 AU + if (r / 1.5e11 > 0.2) { + accept = true; + } + } + const theta = uniform(0, 2 * Math.PI); + const x = r * Math.cos(theta); + const y = r * Math.sin(theta); + const v = Math.sqrt(G * Mstar / r); + const perturbedV = v + v / 1000 * uniform(-1, 1); // Perturb the velocities ever so slightly + const vTheta = Math.atan2(y, x); + coords[0][i] = x; + coords[1][i] = y; + coords[2][i] = -perturbedV * Math.sin(vTheta); + coords[3][i] = perturbedV * Math.cos(vTheta); + } + + //console.log('Initial coords:', coords); + + + let masses = Array(nBodies).fill(Mp); // Initialize masses + masses[0] = Mstar; // Make index one special as the central star + coords[0][0] = 0; + coords[1][0] = 0; + coords[2][0] = 0; + coords[3][0] = 0; // Initialize central star at origin with no velocity + const yearSec = 365 * 24 * 3600; + const time = Array.from({ length: nTPts }, (_, i) => i * tStop / (nTPts - 1) * yearSec); // Years -> s + let t = time[0]; + const deltaT = time[1] - time[0]; + let tInd = 0; + const coordsRecord = [deepCopyCoordsArray(coords)]; + const massRecord = [masses.slice()]; // Initialize records with initial conditions + + + while (tInd < nTPts && nBodies > nBodiesStop) { + //console.log('Initial coords:', coords); + [coords, masses, nBodies] = nBodyStep(coords, masses, deltaT, 10 * 1.5e11, nBodies, G); // Update + coordsRecord.push(deepCopyCoordsArray(coords)); + massRecord.push(masses.slice()); // Add to records + tInd++; + t = time[tInd]; + //console.log(`currently at t = ${(t / yearSec).toFixed(2)} years\r`); + } + console.log(`final time = ${time[tInd] / yearSec} years with ${nBodies} bodies remaining`); + + // Set button text to Start Simulation + btn.innerHTML = prevText; + + return [coordsRecord, massRecord, time.slice(0, tInd + 1)]; +} + + +function initCondGen(nBodies, vRange = [-7e3, 7e3], posRange = [-35, 35]) { + const m = Array.from({length: nBodies}, () => Math.random() * 1500 / 10); + + const rad = m.map(x => Math.pow(x, 0.8)); + const minV = vRange[0], maxV = vRange[1]; + const minPos = posRange[0], maxPos = posRange[1]; + const posList = []; + + function checkPos(randPos, n, posList, rad) { + for (let i = 0; i < n - 1; i++) { + const dist = Math.sqrt(Math.pow(posList[i][0] - randPos[0], 2) + Math.pow(posList[i][1] - randPos[1], 2)); + if (dist * 1.5e11 < (rad[n] + rad[i])) { + return false; + } + } + return true; + } + + function genPos(nBodies, posList, rad, minPos, maxPos) { + posList.push([Math.random() * (maxPos - minPos) + minPos, Math.random() * (maxPos - minPos) + minPos]); + for (let n = 1; n < nBodies; n++) { + let acceptPos = false; + while (acceptPos === false) { + const randPos = [Math.random() * (maxPos - minPos) + minPos, Math.random() * (maxPos - minPos) + minPos]; + acceptPos = checkPos(randPos, n, posList, rad); + if (acceptPos === true) { + posList.push(randPos); + } + } + } + return posList; + } + + const pos = genPos(nBodies, posList, rad, minPos, maxPos).map(x => x.map(y => y * 1.5e11)); + const coords = [new Array(nBodies).fill(0), new Array(nBodies).fill(0), new Array(nBodies).fill(0), new Array(nBodies).fill(0)]; + const v = []; + + for (let i = 0; i < nBodies; i++) { + coords[0][i] = pos[i][0]; + coords[1][i] = pos[i][1]; + const V = [Math.random() * (maxV - minV) + minV, Math.random() * (maxV - minV) + minV]; + v.push(V); + coords[2][i] = V[0]; + coords[3][i] = V[1]; + } + + return {m: m.map(x => x * 2e30), rad: rad.map(x => x * 7e8), coords: coords}; +} + + +function calculateAndPlot() { + try { + Plotly.purge("plot"); + } catch (e) { + console.log(e); + } + + if (plotOrbit===true) { + let traceSun = { + x: [sun.x], + y: [sun.y], + mode: "markers", + marker: { + symbol: "star", + size: 10, + color: "gold", + }, + name: "Sun", + }; + + const traceEarth = { + x: earth.x, + y: earth.y, + mode: "lines", + line: { + color: "white" + }, + name: "Earth", + }; + + const traceOrbit = { + x: circle.x, + y:circle.y, + mode: "lines", + line: { + color: "crimson", + dash: "dash" + }, + name: "1 AU Circle", + }; + + const earthSunLayout = { + title: "Earth-Sun Orbit", + xaxis: { + title: "x [AU]", + range: [-1.1,1.1], + showgrid: true, + gridcolor: "rgba(255,255,255,0.5)", + gridwidth: 1, + zeroline: true, + tickmode: "auto", + nticks: 5, + }, + yaxis: { + title: "y [AU]", + range: [-1.1,1.1], + showgrid: true, + gridcolor: "rgba(255,255,255,0.5)", + gridwidth: 1, + zeroline: false, + tickmode: "auto", + nticks: 5, + }, + margin: { + l: 50, + r: 50, + b: 50, + t: 50, + pad: 4, + }, + paper_bgcolor: "black", + plot_bgcolor: "black", + }; + Plotly.newPlot("plot",[traceSun,traceEarth,traceOrbit], earthSunLayout); + } else if (plotRandom==true) { + + var [coordsRecordR, _, tR] = genNBodyResults(nBodies,1,nBodies*2); + //console.log(coordsRecordR); + const yearSec = 365 * 24 * 3600; + + function createFrame(coordsR) { + if (!coordsR || !coordsR[0] || !coordsR[1]) { + return []; + } + + const traceCentralStar = { + x: [coordsR[0][0] / 1.5e11], + y: [coordsR[1][0] / 1.5e11], + mode: 'markers', + type: 'scatter', + name: 'Central star', + marker: { color: 'gold', symbol: 'star', size: 10 }, + }; + + const xCoords = coordsR[0].slice(1).map(x => x / 1.5e11); + const yCoords = coordsR[1].slice(1).map(y => y / 1.5e11); + + const traceOtherBodies = { + x: xCoords, + y: yCoords, + mode: 'markers', + type: 'scatter', + name: '', + marker: { color: 'dodgerblue', symbol: 'circle', size: 2 }, + }; + + return [traceCentralStar, traceOtherBodies]; + } + + + function createLayout(i) { + return { + title: { + text: `N-Body Problem`,//= ${Number(t[i] / yearSec).toFixed(3)} years`, + x: 0.03, + y: 0.97, + xanchor: 'left', + yanchor: 'top', + font: { size: 14 }, + }, + xaxis: { title: 'x [AU]', range: [-2.1, 2.1] }, + yaxis: { title: 'y [AU]', range: [-2.1, 2.1], scaleanchor: 'x', scaleratio: 1 }, + showlegend: false, + margin: { l: 60, r: 40, t: 40, b: 40 }, + width: 800, + height: 800, + plot_bgcolor: 'black', + }; +} + + function animateNBodyProblem() { + const nFrames = tR.length; + + for (let i = 0; i < nFrames; i++) { + const frameData = createFrame(coordsRecordR[i]); + const layout = createLayout(i); + //Plotly.newPlot(plotDiv, frameData, layout); + try { + Plotly.animate("plot", { + data: frameData, layout: layout + }, { + staticPlot: true, + transition: { + duration: 0, + }, + frame: { + duration: 0, + redraw: false, + } + }); + } catch (err) { + Plotly.newPlot('plot', frameData, layout); + } + } +} + +animateNBodyProblem(); + + + } else if (plotClassic==true) { + // Initial conditions setup + let M = [1, 1, 1]; + let x = [-0.97000436, 0.0, 0.97000436]; + let y = [0.24208753, 0.0, -0.24208753]; + let vx = [0.4662036850, -0.933240737, 0.4662036850]; + let vy = [0.4323657300, -0.86473146, 0.4323657300]; + let Ei = -1 / Math.sqrt(Math.pow(2 * 0.97000436, 2) + Math.pow(2 * 0.24208753, 2)) - 2 / Math.sqrt(Math.pow(0.97000436, 2) + Math.pow(0.24208753, 2)) + 0.5 * (math.sum(math.add(math.dotPow(vx, 2), math.dotPow(vy, 2)))); + + function linspace(start, stop, num) { + const step = (stop - start) / (num - 1); + return Array.from({length: num}, (_, i) => start + (step * i)); + } + + let coords = [x, y, vx, vy]; + const time = linspace(0, 6.3259, 1001); + let deltaT = time[1] - time[0]; + + let X = math.zeros(3, time.length).toArray(); + let Y = math.zeros(3, time.length).toArray(); + let VX = math.zeros(3, time.length).toArray(); + let VY = math.zeros(3, time.length).toArray(); + + for (let i = 0; i < time.length; i++) { + coords = step(coords, M, deltaT, 3, 1); + X.forEach((_, idx) => X[idx][i] = coords[0][idx]); + Y.forEach((_, idx) => Y[idx][i] = coords[1][idx]); + VX.forEach((_, idx) => VX[idx][i] = coords[2][idx]); + VY.forEach((_, idx) => VY[idx][i] = coords[3][idx]); + } + function plotClassicFunc() { + var tailLength = 1; + if (plotIndex < tailLength) { + tailLength = 0; + } else if (plotIndex > time.length) { + plotIndex = 0; + } else { + tailLength = plotIndex - tailLength; + } + + var currentIndex = plotIndex; + + try { + time[currentIndex].toFixed(3); + } catch (e) { + currentIndex = 0; + } + + const data = [ + { + x: X[0].slice(tailLength, currentIndex), + y: Y[0].slice(tailLength, currentIndex), + mode: 'lines+markers', + marker: { + symbol: 'star', + size: 8, + line: { width: 0 }, + }, + line: { + width: 2, + }, + name: '', + }, + { + x: X[1].slice(tailLength, currentIndex), + y: Y[1].slice(tailLength, currentIndex), + mode: 'lines+markers', + marker: { + symbol: 'star', + size: 8, + line: { width: 0 }, + }, + line: { + width: 2, + }, + name: '', + }, + { + x: X[2].slice(tailLength, currentIndex), + y: Y[2].slice(tailLength, currentIndex), + mode: 'lines+markers', + marker: { + symbol: 'star', + size: 8, + line: { width: 0 }, + }, + line: { + width: 2, + }, + name: '', + }, + ]; + + // width: 1000, height: 400 + const layout = { + title: '∞ Three-Body Problem: t = ' + time[currentIndex].toFixed(3), + xaxis: { + title: 'x', + range: [-1.1,1.1] + }, + yaxis: { + title: 'y', + scaleanchor: 'x', + scaleratio: 1, + range: [-0.5,0.5] + }, + plot_bgcolor: 'black', + paper_bgcolor: 'black', + font: { + color: 'white', + }, + }; + + try { + Plotly.animate("plot", { + data: data, layout: layout + }, { + staticPlot: true, + transition: { + duration: 0, + }, + frame: { + duration: 0, + redraw: false, + } + }); + } catch (err) { + Plotly.newPlot('plot', data, layout); + } + + + plotIndex += delay; + if (plotClassic===true) { + try { + requestAnimationFrame(plotClassicFunc); + } + catch (err) { + console.log(err) + } + } + + } + + plotClassicFunc(); + + } +} + diff --git a/docs/feed.rss b/docs/feed.rss index f7a4852..760ae20 100644 --- a/docs/feed.rss +++ b/docs/feed.rss @@ -4,8 +4,8 @@ <title>Navan's Archive</title> <description>Rare Tips, Tricks and Posts</description> <link>https://web.navan.dev/</link><language>en</language> - <lastBuildDate>Sun, 30 Apr 2023 23:19:46 -0000</lastBuildDate> - <pubDate>Sun, 30 Apr 2023 23:19:46 -0000</pubDate> + <lastBuildDate>Mon, 01 May 2023 00:26:41 -0000</lastBuildDate> + <pubDate>Mon, 01 May 2023 00:26:41 -0000</pubDate> <ttl>250</ttl> <atom:link href="https://web.navan.dev/feed.rss" rel="self" type="application/rss+xml"/> @@ -4142,6 +4142,692 @@ Seeing that you are reading this on Mastodon, and that I have updated this secti <p>This post requires JavaScript to be viewed properly :(</p> +<p>Adapted from the Numerics Tutorial - <a rel="noopener" target="_blank" href="https://github.com/kirklong/ThreeBodyBot/tree/master/NumericsTutorial">kirklong/ThreeBodyBot</a>. The Julia code has been rewritten in JavaScript.</p> + +<p>Workflow:</p> + +<ul> +<li><p>Understand the problem</p></li> +<li><p>Visualise a basic orbit</p></li> +<li><p>Solve and plot the classic figure-8 orbit</p></li> +<li><p>random n-body solution generator</p></li> +</ul> + +<p><strong>To workaround memory issues, the simulations are only run on-demand when the user clicks the respective button. Scroll down to the bottom of the page to see the results.</strong></p> + +<h2>The n-body problem</h2> + +<p>The n-body problem is a classic puzzle in physics (and thus astrophysics) and mathematics that deals with predicting the motion of multiple celestial objects that interact with each other through gravitational forces. </p> + +<p>Imagine you are observing a <em>cosmic dance</em> between multiple celestial bodies, all tugging on one another as they move through space. The n-body problem aims to undersand and predict the paths of these objects as they move through space.</p> + +<p>When <code>n=2</code>, i.e we have only two objects, say the Earth and the Moon, we can easily apply Newtonian physics to predict their motion. However, when <code>n>2</code>, the problem becomes much more difficult to solve analytically. This is because each object feels the gravitational pull from all other objects, and thus the equations of motion become coupled and non-linear. </p> + +<p>As the number of objects increases, finding an exact solution becomes impossible, and we rely on analyticals approximations.</p> + +<h2>Visualising a basic orbit</h2> + +<p>If we want to create a n-body simulation in our browser, we need to figure out how we are going to visualise the motion of the objects. There are a few ways to do this, but the easiest is to use Plotly.js, a JavaScript library for creating interactive graphs. (An alternative is to use the HTML5 canvas element).</p> + +<div class="codehilite"> +<pre><span></span><code><span class="cm">/*</span> +<span class="cm"> * Earth - Sun Orbit Plot</span> +<span class="cm"> * Taken from Numerics tutorial</span> +<span class="cm"> */</span><span class="w"></span> + +<span class="kd">const</span><span class="w"> </span><span class="nx">G</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">6.67e-11</span><span class="p">;</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">Msun</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">2e30</span><span class="p">;</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">AU</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1.5e11</span><span class="p">;</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">v0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sqrt</span><span class="p">(</span><span class="nx">G</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">Msun</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">AU</span><span class="p">);</span><span class="w"> </span><span class="c1">// SI</span><span class="w"></span> + +<span class="kd">function</span><span class="w"> </span><span class="nx">dR</span><span class="p">(</span><span class="nx">r</span><span class="p">,</span><span class="w"> </span><span class="nx">v</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">dv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="nx">G</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">Msun</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">3</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="mf">0</span><span class="p">],</span><span class="w"> </span><span class="o">-</span><span class="nx">G</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">Msun</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">3</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="mf">1</span><span class="p">]];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">dr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[...</span><span class="nx">v</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">dr</span><span class="p">,</span><span class="w"> </span><span class="nx">dv</span><span class="p">];</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="c1">// initialize system</span><span class="w"></span> +<span class="kd">let</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="nx">AU</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">];</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">theta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">atan2</span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="mf">1</span><span class="p">],</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="mf">0</span><span class="p">]);</span><span class="w"></span> +<span class="kd">let</span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="nx">v0</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sin</span><span class="p">(</span><span class="nx">theta</span><span class="p">),</span><span class="w"> </span><span class="nx">v0</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">cos</span><span class="p">(</span><span class="nx">theta</span><span class="p">)];</span><span class="w"></span> + +<span class="kd">const</span><span class="w"> </span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="w"> </span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="mf">1001</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">(</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">100</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">0.0</span><span class="p">);</span><span class="w"> </span><span class="c1">// years</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">yearSec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">365</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">3600</span><span class="p">;</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">dt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">t</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">t</span><span class="p">[</span><span class="mf">0</span><span class="p">])</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">yearSec</span><span class="p">;</span><span class="w"> </span><span class="c1">// s</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">x4Plot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="w"> </span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="nx">t</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="mf">0</span><span class="p">);</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">y4Plot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="w"> </span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="nx">t</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="mf">0</span><span class="p">);</span><span class="w"></span> + +<span class="c1">// integrate using RK4!</span><span class="w"></span> +<span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">t</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">k1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">dR</span><span class="p">(</span><span class="nx">r</span><span class="p">,</span><span class="w"> </span><span class="nx">v</span><span class="p">).</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">y</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">dt</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">k2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">dR</span><span class="p">(</span><span class="nx">r</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">ri</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">ri</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k1</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">2</span><span class="p">),</span><span class="w"> </span><span class="nx">v</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">vi</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">vi</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k1</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">2</span><span class="p">)).</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">y</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">dt</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">k3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">dR</span><span class="p">(</span><span class="nx">r</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">ri</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">ri</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k2</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">2</span><span class="p">),</span><span class="w"> </span><span class="nx">v</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">vi</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">vi</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k2</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">2</span><span class="p">)).</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">y</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">dt</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">k4</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">dR</span><span class="p">(</span><span class="nx">r</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">ri</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">ri</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k3</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">j</span><span class="p">]),</span><span class="w"> </span><span class="nx">v</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">vi</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">vi</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k3</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">j</span><span class="p">])).</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">y</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">dt</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">ri</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">ri</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">k1</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">k2</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">k3</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k4</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">j</span><span class="p">])</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">6</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">v</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">vi</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">vi</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">k1</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">k2</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">k3</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k4</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">j</span><span class="p">])</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">6</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">x4Plot</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="nx">y4Plot</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="mf">1</span><span class="p">];</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="c1">// make data for plot</span><span class="w"></span> +<span class="kd">var</span><span class="w"> </span><span class="nx">sun</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="p">};</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">earth</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nx">x4Plot</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">AU</span><span class="p">),</span><span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="nx">y4Plot</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">y</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">AU</span><span class="p">)</span><span class="w"> </span><span class="p">};</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">circle</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="w"> </span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="mf">1001</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">(</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">cos</span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">100</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">PI</span><span class="p">)),</span><span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="w"> </span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="mf">1001</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">(</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sin</span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">100</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">PI</span><span class="p">))</span><span class="w"> </span><span class="p">};</span><span class="w"></span> +</code></pre> +</div> + +<p>This code simulates the orbit of Earth around the Sun, using a numerical method called the Runge-Kutta 4th order (RK4) method.</p> + +<p>First, we define some constants:</p> + +<p>G: the gravitational constant (6.67e-11 N m²/kg²) +Msun: the mass of the Sun (2e30 kg) +AU: an astronomical unit, the average distance between Earth and Sun (1.5e11 m) +v0: the initial velocity of Earth, calculated from its distance to the Sun +Next, the function dR takes the position r and velocity v of Earth as input and returns the rate of change in position (dr) and the rate of change in velocity (dv) using the gravitational force formula.</p> + +<p>We then initialize the position r and velocity v of Earth, and create an array t that represents time in years, divided into 1001 steps. We also define yearSec as the number of seconds in a year and dt as the time step in seconds.</p> + +<p>Now, we integrate the Earth's motion using the RK4 method. For each time step, we calculate the rates of change for position and velocity (k1, k2, k3, k4) and update Earth's position and velocity based on these. We store the updated position in x4Plot and y4Plot.</p> + +<p>Finally, we normalize the position data by dividing it by the astronomical unit (AU) to make it more visually meaningful. We also create a circle for reference, which represents a perfect circular orbit. The code ends with the data for the Sun's position, Earth's orbit, and the reference circle ready to be plotted.</p> + +<h3>Plotting the orbit</h3> + +<p>Now that we have the data for the Sun's position, Earth's orbit, and the reference circle, we can plot them using Plotly.js. + <div class="codehilite"> + <pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="nx">traceSun</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="nx">sun</span><span class="p">.</span><span class="nx">x</span><span class="p">],</span><span class="w"></span> + <span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="nx">sun</span><span class="p">.</span><span class="nx">y</span><span class="p">],</span><span class="w"></span> + <span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s2">"markers"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">marker</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">symbol</span><span class="o">:</span><span class="w"> </span><span class="s2">"star"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">size</span><span class="o">:</span><span class="w"> </span><span class="mf">10</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">color</span><span class="o">:</span><span class="w"> </span><span class="s2">"gold"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s2">"Sun"</span><span class="p">,</span><span class="w"></span> + <span class="p">};</span><span class="w"></span> + <br /> + <span class="kd">const</span><span class="w"> </span><span class="nx">traceEarth</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nx">earth</span><span class="p">.</span><span class="nx">x</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="nx">earth</span><span class="p">.</span><span class="nx">y</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s2">"lines"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">color</span><span class="o">:</span><span class="w"> </span><span class="s2">"white"</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s2">"Earth"</span><span class="p">,</span><span class="w"></span> + <span class="p">};</span><span class="w"></span> + <br /> + <span class="kd">const</span><span class="w"> </span><span class="nx">traceOrbit</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nx">circle</span><span class="p">.</span><span class="nx">x</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="nx">circle</span><span class="p">.</span><span class="nx">y</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s2">"lines"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">color</span><span class="o">:</span><span class="w"> </span><span class="s2">"crimson"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">dash</span><span class="o">:</span><span class="w"> </span><span class="s2">"dash"</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s2">"1 AU Circle"</span><span class="p">,</span><span class="w"></span> + <span class="p">};</span><span class="w"></span> + <br /> + <span class="kd">const</span><span class="w"> </span><span class="nx">earthSunLayout</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s2">"Earth-Sun Orbit"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">xaxis</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s2">"x [AU]"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">range</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mf">1.1</span><span class="p">,</span><span class="mf">1.1</span><span class="p">],</span><span class="w"></span> + <span class="w"> </span><span class="nx">showgrid</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">gridcolor</span><span class="o">:</span><span class="w"> </span><span class="s2">"rgba(255,255,255,0.5)"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">gridwidth</span><span class="o">:</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">zeroline</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">tickmode</span><span class="o">:</span><span class="w"> </span><span class="s2">"auto"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">nticks</span><span class="o">:</span><span class="w"> </span><span class="mf">5</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">yaxis</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s2">"y [AU]"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">range</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mf">1.1</span><span class="p">,</span><span class="mf">1.1</span><span class="p">],</span><span class="w"></span> + <span class="w"> </span><span class="nx">showgrid</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">gridcolor</span><span class="o">:</span><span class="w"> </span><span class="s2">"rgba(255,255,255,0.5)"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">gridwidth</span><span class="o">:</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">zeroline</span><span class="o">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">tickmode</span><span class="o">:</span><span class="w"> </span><span class="s2">"auto"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">nticks</span><span class="o">:</span><span class="w"> </span><span class="mf">5</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">margin</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">l</span><span class="o">:</span><span class="w"> </span><span class="mf">50</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">r</span><span class="o">:</span><span class="w"> </span><span class="mf">50</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">b</span><span class="o">:</span><span class="w"> </span><span class="mf">50</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">t</span><span class="o">:</span><span class="w"> </span><span class="mf">50</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">pad</span><span class="o">:</span><span class="w"> </span><span class="mf">4</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">paper<em>bgcolor</span><span class="o">:</span><span class="w"> </span><span class="s2">"black"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">plot</em>bgcolor</span><span class="o">:</span><span class="w"> </span><span class="s2">"black"</span><span class="p">,</span><span class="w"></span> + <span class="p">};</span><span class="w"></span> + <span class="nx">Plotly</span><span class="p">.</span><span class="nx">newPlot</span><span class="p">(</span><span class="s2">"plot"</span><span class="p">,[</span><span class="nx">traceSun</span><span class="p">,</span><span class="nx">traceEarth</span><span class="p">,</span><span class="nx">traceOrbit</span><span class="p">],</span><span class="w"> </span><span class="nx">earthSunLayout</span><span class="p">);</span><span class="w"></span> + </code></pre> + </div></p> + +<h2>Figure of 8 orbit</h2> + +<p>The figure of 8 solution in the three-body problem refers to a unique and special trajectory where three celestial bodies (e.g., planets, stars) move in a figure of 8 shaped pattern around their mutual center of mass. This is special because it represents a stable and periodic solution to the three-body problem, which is known for its complexity and lack of general solutions.</p> + +<p>In the figure of 8 solution, each of the three bodies follows the same looping path, but with a phase difference such that when one body is at one end of the loop, the other two are symmetrically positioned elsewhere along the path. The bodies maintain equal distances from each other throughout their motion, and their velocities and positions are perfectly balanced to maintain this periodic motion.</p> + +<p>The figure of 8 is interesting because:</p> + +<ul> +<li><p>It is a relatively stable solution, which means that the objects continue to follow the same looping path almost indefinitely.</p></li> +<li><p>It breaks down the notion that no simple periodic solutions exist for the three-body problem.</p></li> +<li><p>It looks cool!</p></li> +</ul> + +<h3>Show me the code</h3> + +<p>The code for this simulation is very similar to the Earth-Sun orbit simulation, except that we now have three bodies instead of two. We also use a different set of initial conditions to generate the figure of 8 orbit.</p> + +<div class="codehilite"> +<pre><span></span><code><span class="kd">function</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">vx</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">vy</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">];</span><span class="w"></span> + +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">delta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">clone</span><span class="p">(</span><span class="nx">coords</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">;</span><span class="w"> </span><span class="nx">n</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">xn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">n</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">yn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">y</span><span class="p">[</span><span class="nx">n</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">deltaVx</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.0</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">deltaVy</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.0</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="nx">n</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">sep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sqrt</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">xn</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">yn</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">y</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span><span class="w"> </span><span class="mf">2</span><span class="p">));</span><span class="w"> </span><span class="c1">// Euclidean distance</span><span class="w"></span> +<span class="w"> </span><span class="nx">deltaVx</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="nx">G</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="nx">xn</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">sep</span><span class="p">,</span><span class="w"> </span><span class="mf">3</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">deltaVy</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="nx">G</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="nx">yn</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">y</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">sep</span><span class="p">,</span><span class="w"> </span><span class="mf">3</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> + +<span class="w"> </span><span class="nx">delta</span><span class="p">[</span><span class="mf">2</span><span class="p">][</span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">deltaVx</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">delta</span><span class="p">[</span><span class="mf">3</span><span class="p">][</span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">deltaVy</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> + +<span class="w"> </span><span class="nx">delta</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">vx</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">delta</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">vy</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">delta</span><span class="p">;</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="kd">function</span><span class="w"> </span><span class="nx">step</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">6.67408313131313e-11</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">k1</span><span class="p">,</span><span class="w"> </span><span class="mf">0.5</span><span class="p">)),</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">k2</span><span class="p">,</span><span class="w"> </span><span class="mf">0.5</span><span class="p">)),</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k4</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">k3</span><span class="p">),</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> + +<span class="w"> </span><span class="nx">coords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">k1</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="mf">2.0</span><span class="p">,</span><span class="w"> </span><span class="nx">k2</span><span class="p">),</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="mf">2.0</span><span class="p">,</span><span class="w"> </span><span class="nx">k3</span><span class="p">),</span><span class="w"> </span><span class="nx">k4</span><span class="p">),</span><span class="w"> </span><span class="mf">1</span><span class="o">/</span><span class="mf">6</span><span class="p">));</span><span class="w"></span> + +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">coords</span><span class="p">;</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="w"> </span><span class="c1">// Initial conditions setup</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">M</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mf">0.97000436</span><span class="p">,</span><span class="w"> </span><span class="mf">0.0</span><span class="p">,</span><span class="w"> </span><span class="mf">0.97000436</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mf">0.24208753</span><span class="p">,</span><span class="w"> </span><span class="mf">0.0</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">0.24208753</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">vx</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mf">0.4662036850</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">0.933240737</span><span class="p">,</span><span class="w"> </span><span class="mf">0.4662036850</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">vy</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mf">0.4323657300</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">0.86473146</span><span class="p">,</span><span class="w"> </span><span class="mf">0.4323657300</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">Ei</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mf">1</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sqrt</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">0.97000436</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">0.24208753</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">))</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sqrt</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="mf">0.97000436</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="mf">0.24208753</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">0.5</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">sum</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">dotPow</span><span class="p">(</span><span class="nx">vx</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">),</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">dotPow</span><span class="p">(</span><span class="nx">vy</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">))));</span><span class="w"></span> + +<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">linspace</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span><span class="w"> </span><span class="nx">stop</span><span class="p">,</span><span class="w"> </span><span class="nx">num</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">step</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">stop</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">start</span><span class="p">)</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="p">(</span><span class="nx">num</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="nx">num</span><span class="p">},</span><span class="w"> </span><span class="p">(</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">start</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">step</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">i</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> + +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">coords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="p">,</span><span class="w"> </span><span class="nx">vx</span><span class="p">,</span><span class="w"> </span><span class="nx">vy</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">time</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">linspace</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">6.3259</span><span class="p">,</span><span class="w"> </span><span class="mf">1001</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">deltaT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span><span class="w"></span> + +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">X</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">zeros</span><span class="p">(</span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">length</span><span class="p">).</span><span class="nx">toArray</span><span class="p">();</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">Y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">zeros</span><span class="p">(</span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">length</span><span class="p">).</span><span class="nx">toArray</span><span class="p">();</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">VX</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">zeros</span><span class="p">(</span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">length</span><span class="p">).</span><span class="nx">toArray</span><span class="p">();</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">VY</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">zeros</span><span class="p">(</span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">length</span><span class="p">).</span><span class="nx">toArray</span><span class="p">();</span><span class="w"></span> + +<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">step</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">M</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">X</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">idx</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">X</span><span class="p">[</span><span class="nx">idx</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">idx</span><span class="p">]);</span><span class="w"></span> +<span class="w"> </span><span class="nx">Y</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">idx</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">Y</span><span class="p">[</span><span class="nx">idx</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">idx</span><span class="p">]);</span><span class="w"></span> +<span class="w"> </span><span class="nx">VX</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">idx</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">VX</span><span class="p">[</span><span class="nx">idx</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">][</span><span class="nx">idx</span><span class="p">]);</span><span class="w"></span> +<span class="w"> </span><span class="nx">VY</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">idx</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">VY</span><span class="p">[</span><span class="nx">idx</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">][</span><span class="nx">idx</span><span class="p">]);</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +</code></pre> +</div> + +<p>The <code>deltaR</code> function computes the rate of change in position and velocity of the celestial bodies based on their current positions, velocities, and masses. It accounts for the gravitational forces between all bodies.</p> + +<p>The <code>step</code> function performs a single RK4 integration step, updating the positions and velocities of the celestial bodies. It uses <code>deltaR</code> to compute the four increments (k1, k2, k3, and k4) and then updates the coordinates accordingly.</p> + +<p>Next, the initial conditions for the figure-8 three-body problem are set. The masses (<code>M</code>), initial positions (<code>x</code>, <code>y</code>), and initial velocities (<code>vx</code>, <code>vy</code>) are provided. <code>Ei</code> calculates the initial total energy of the system.</p> + +<p>The <code>linspace</code> function is defined to create a linearly spaced array of time points. <code>coords</code> is an array containing the positions and velocities for all bodies. The <code>time</code> array is created using <code>linspace</code>, and <code>deltaT</code> is set as the time step.</p> + +<p><code>X</code>, <code>Y</code>, <code>VX</code>, and <code>VY</code> are 2D arrays that will store the positions and velocities of the celestial bodies over time. They are initialized with zeros and will be updated in the loop.</p> + +<p>Finally, a loop iterates over each time step, updating the positions and velocities of the celestial bodies using the <code>step</code> function. The updated coordinates are stored in the <code>X</code>, <code>Y</code>, <code>VX</code>, and <code>VY</code> arrays.</p> + +<h3>Animation?</h3> + +<p>Now that we have time-series data, we need to animate it. We can use Plotly's animate function, as this does not force a full re-render, saving us some precious GPU and CPU cycles when we are trying to run this in the browser itself + <div class="codehilite"> + <pre><span></span><code><span class="kd">function</span><span class="w"> </span><span class="nx">plotClassicFunc</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">tailLength</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span><span class="w"></span> + <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">plotIndex</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">tailLength</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">tailLength</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">plotIndex</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">plotIndex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">tailLength</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">plotIndex</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">tailLength</span><span class="p">;</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"></span> + <br /> + <span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">currentIndex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">plotIndex</span><span class="p">;</span><span class="w"></span> + <br /> + <span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="nx">currentIndex</span><span class="p">].</span><span class="nx">toFixed</span><span class="p">(</span><span class="mf">3</span><span class="p">);</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="nx">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">currentIndex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"></span> + <br /> + <span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="w"></span> + <span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nx">X</span><span class="p">[</span><span class="mf">0</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="nx">tailLength</span><span class="p">,</span><span class="w"> </span><span class="nx">currentIndex</span><span class="p">),</span><span class="w"></span> + <span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="nx">Y</span><span class="p">[</span><span class="mf">0</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="nx">tailLength</span><span class="p">,</span><span class="w"> </span><span class="nx">currentIndex</span><span class="p">),</span><span class="w"></span> + <span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s1">'lines+markers'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">marker</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">symbol</span><span class="o">:</span><span class="w"> </span><span class="s1">'star'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">size</span><span class="o">:</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s1">''</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nx">X</span><span class="p">[</span><span class="mf">1</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="nx">tailLength</span><span class="p">,</span><span class="w"> </span><span class="nx">currentIndex</span><span class="p">),</span><span class="w"></span> + <span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="nx">Y</span><span class="p">[</span><span class="mf">1</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="nx">tailLength</span><span class="p">,</span><span class="w"> </span><span class="nx">currentIndex</span><span class="p">),</span><span class="w"></span> + <span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s1">'lines+markers'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">marker</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">symbol</span><span class="o">:</span><span class="w"> </span><span class="s1">'star'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">size</span><span class="o">:</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s1">''</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nx">X</span><span class="p">[</span><span class="mf">2</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="nx">tailLength</span><span class="p">,</span><span class="w"> </span><span class="nx">currentIndex</span><span class="p">),</span><span class="w"></span> + <span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="nx">Y</span><span class="p">[</span><span class="mf">2</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="nx">tailLength</span><span class="p">,</span><span class="w"> </span><span class="nx">currentIndex</span><span class="p">),</span><span class="w"></span> + <span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s1">'lines+markers'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">marker</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">symbol</span><span class="o">:</span><span class="w"> </span><span class="s1">'star'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">size</span><span class="o">:</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s1">''</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="p">];</span><span class="w"></span> + <br /> + <span class="c1">// width: 1000, height: 400</span><span class="w"></span> + <span class="kd">const</span><span class="w"> </span><span class="nx">layout</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s1">'∞ Three-Body Problem: t = '</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="nx">currentIndex</span><span class="p">].</span><span class="nx">toFixed</span><span class="p">(</span><span class="mf">3</span><span class="p">),</span><span class="w"></span> + <span class="w"> </span><span class="nx">xaxis</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s1">'x'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">range</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mf">1.1</span><span class="p">,</span><span class="mf">1.1</span><span class="p">]</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">yaxis</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s1">'y'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">scaleanchor</span><span class="o">:</span><span class="w"> </span><span class="s1">'x'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">scaleratio</span><span class="o">:</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">range</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mf">0.5</span><span class="p">,</span><span class="mf">0.5</span><span class="p">]</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">plot<em>bgcolor</span><span class="o">:</span><span class="w"> </span><span class="s1">'black'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">paper</em>bgcolor</span><span class="o">:</span><span class="w"> </span><span class="s1">'black'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">font</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">color</span><span class="o">:</span><span class="w"> </span><span class="s1">'white'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="p">};</span><span class="w"></span> + <br /> + <span class="k">try</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="nx">Plotly</span><span class="p">.</span><span class="nx">animate</span><span class="p">(</span><span class="s2">"plot"</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">data</span><span class="o">:</span><span class="w"> </span><span class="nx">data</span><span class="p">,</span><span class="w"> </span><span class="nx">layout</span><span class="o">:</span><span class="w"> </span><span class="nx">layout</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">staticPlot</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">transition</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">duration</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">frame</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">duration</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">redraw</span><span class="o">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"></span> + <span class="w"> </span><span class="p">});</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">Plotly</span><span class="p">.</span><span class="nx">newPlot</span><span class="p">(</span><span class="s1">'plot'</span><span class="p">,</span><span class="w"> </span><span class="nx">data</span><span class="p">,</span><span class="w"> </span><span class="nx">layout</span><span class="p">);</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"></span> + <br /> + <br /> + <span class="nx">plotIndex</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">delay</span><span class="p">;</span><span class="w"></span> + <span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">plotClassic</span><span class="o">===</span><span class="kc">true</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">requestAnimationFrame</span><span class="p">(</span><span class="nx">plotClassicFunc</span><span class="p">);</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"></span> + <span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"></span> + <span class="p">}</span><span class="w"></span> + <br /> + <span class="p">}</span><span class="w"></span> + </code></pre> + </div></p> + +<h2>"General" N-Body Solver</h2> + +<h3>Show me the code!</h3> + +<div class="codehilite"> +<pre><span></span><code><span class="kd">function</span><span class="w"> </span><span class="nx">step</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">6.67408313131313e-11</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">k1</span><span class="p">,</span><span class="w"> </span><span class="mf">0.5</span><span class="p">)),</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">k2</span><span class="p">,</span><span class="w"> </span><span class="mf">0.5</span><span class="p">)),</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k4</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">k3</span><span class="p">),</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> + +<span class="w"> </span><span class="nx">coords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">k1</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="mf">2.0</span><span class="p">,</span><span class="w"> </span><span class="nx">k2</span><span class="p">),</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="mf">2.0</span><span class="p">,</span><span class="w"> </span><span class="nx">k3</span><span class="p">),</span><span class="w"> </span><span class="nx">k4</span><span class="p">),</span><span class="w"> </span><span class="mf">1</span><span class="o">/</span><span class="mf">6</span><span class="p">));</span><span class="w"></span> + +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">coords</span><span class="p">;</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="kd">function</span><span class="w"> </span><span class="nx">detectCollisionsEscape</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">maxSep</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="p">,</span><span class="w"> </span><span class="nx">vx</span><span class="p">,</span><span class="w"> </span><span class="nx">vy</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">V</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">vx</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">v</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sqrt</span><span class="p">(</span><span class="nx">v</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">vy</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">R</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">V</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">v</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">collision</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="nx">collisionInds</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="nx">escape</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="nx">escapeInd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">n</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">rn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">R</span><span class="p">[</span><span class="nx">n</span><span class="p">],</span><span class="w"> </span><span class="nx">xn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">n</span><span class="p">],</span><span class="w"> </span><span class="nx">yn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">y</span><span class="p">[</span><span class="nx">n</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="nx">n</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">minSep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">rn</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">R</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">sep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sqrt</span><span class="p">((</span><span class="nx">xn</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">yn</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">y</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">sep</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">minSep</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">collision</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">collisionInds</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">sep</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="nx">maxSep</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">escape</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">escapeInd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">n</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">collision</span><span class="p">,</span><span class="w"> </span><span class="nx">collisionInds</span><span class="p">,</span><span class="w"> </span><span class="nx">escape</span><span class="p">,</span><span class="w"> </span><span class="nx">escapeInd</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">collision</span><span class="p">,</span><span class="w"> </span><span class="nx">collisionInds</span><span class="p">,</span><span class="w"> </span><span class="nx">escape</span><span class="p">,</span><span class="w"> </span><span class="nx">escapeInd</span><span class="p">];</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="kd">function</span><span class="w"> </span><span class="nx">nBodyStep</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">maxSep</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">6.67408313131313e-11</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// Similar to our step function before, but keeping track of collisions</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">step</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">);</span><span class="w"> </span><span class="c1">// Update the positions as we did before</span><span class="w"></span> +<span class="w"> </span><span class="c1">//console.log(detectCollisionsEscape(coords, deltaT, maxSep));</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="nx">collision</span><span class="p">,</span><span class="w"> </span><span class="nx">collisionInds</span><span class="p">,</span><span class="w"> </span><span class="nx">escape</span><span class="p">,</span><span class="w"> </span><span class="nx">escapeInd</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">detectCollisionsEscape</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">maxSep</span><span class="p">);</span><span class="w"> </span><span class="c1">// Detect collisions/escapes</span><span class="w"></span> + + +<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">collision</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// Do inelastic collision and delete extra body (2 -> 1)</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">i1</span><span class="p">,</span><span class="w"> </span><span class="nx">i2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">collisionInds</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">x1</span><span class="p">,</span><span class="w"> </span><span class="nx">x2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">i1</span><span class="p">],</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">i2</span><span class="p">]];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">y1</span><span class="p">,</span><span class="w"> </span><span class="nx">y2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">i1</span><span class="p">],</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">i2</span><span class="p">]];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">vx1</span><span class="p">,</span><span class="w"> </span><span class="nx">vx2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">][</span><span class="nx">i1</span><span class="p">],</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">][</span><span class="nx">i2</span><span class="p">]];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">vy1</span><span class="p">,</span><span class="w"> </span><span class="nx">vy2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">][</span><span class="nx">i1</span><span class="p">],</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">][</span><span class="nx">i2</span><span class="p">]];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">px1</span><span class="p">,</span><span class="w"> </span><span class="nx">px2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">vx1</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i2</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">vx2</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">py1</span><span class="p">,</span><span class="w"> </span><span class="nx">py2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">vy1</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i2</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">vy2</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">px</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">px1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">px2</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">py</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">py1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">py2</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">newM</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i2</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">vfx</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">px</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">newM</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">vfy</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">py</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">newM</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">x1</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">x2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i2</span><span class="p">])</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="p">(</span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i2</span><span class="p">]);</span><span class="w"> </span><span class="c1">// Center of mass</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">y1</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">y2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i2</span><span class="p">])</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="p">(</span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i2</span><span class="p">]);</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">][</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">vfx</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">][</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">vfy</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">].</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i2</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">].</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i2</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">].</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i2</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">].</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i2</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">newM</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">masses</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i2</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">nBodies</span><span class="o">--</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="c1">// Could also implement condition for escape where we stop calculating forces but I'm too lazy for now</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">collision</span><span class="p">,</span><span class="w"> </span><span class="nx">collisionInds</span><span class="p">,</span><span class="w"> </span><span class="nx">escape</span><span class="p">,</span><span class="w"> </span><span class="nx">escapeInd</span><span class="p">];</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="kd">function</span><span class="w"> </span><span class="nx">uniform</span><span class="p">(</span><span class="nx">min</span><span class="p">,</span><span class="w"> </span><span class="nx">max</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="nx">max</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">min</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">min</span><span class="p">;</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="kd">function</span><span class="w"> </span><span class="nx">deepCopyCoordsArray</span><span class="p">(</span><span class="nx">arr</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">arr</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">innerArr</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">innerArr</span><span class="p">.</span><span class="nx">slice</span><span class="p">());</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="kd">function</span><span class="w"> </span><span class="nx">genNBodyResults</span><span class="p">(</span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">tStop</span><span class="p">,</span><span class="w"> </span><span class="nx">nTPts</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodiesStop</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">10</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">6.67408313131313e-11</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + +<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">btn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">"startSim3"</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="c1">// Set button text to Solving</span><span class="w"></span> +<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">prevText</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">btn</span><span class="p">.</span><span class="nx">innerHTML</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">btn</span><span class="p">.</span><span class="nx">innerHTML</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Solving..."</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">coords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nb">Array</span><span class="p">(</span><span class="nx">nBodies</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="mf">0</span><span class="p">),</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="nx">nBodies</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="mf">0</span><span class="p">),</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="nx">nBodies</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="mf">0</span><span class="p">),</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="nx">nBodies</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="mf">0</span><span class="p">)];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">Mstar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">2e30</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">Mp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">Mstar</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">1e4</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// Initialize coordinates on ~Keplerian orbits</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">accept</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">accept</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// Prevent a particle from spawning within 0.2 AU too close to "star"</span><span class="w"></span> +<span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">1.5e11</span><span class="p">;</span><span class="w"> </span><span class="c1">// Say radius of 2 AU</span><span class="w"></span> +<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">1.5e11</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0.2</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">accept</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">theta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">uniform</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">PI</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">cos</span><span class="p">(</span><span class="nx">theta</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sin</span><span class="p">(</span><span class="nx">theta</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sqrt</span><span class="p">(</span><span class="nx">G</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">Mstar</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">r</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">perturbedV</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">1000</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">uniform</span><span class="p">(</span><span class="o">-</span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"> </span><span class="c1">// Perturb the velocities ever so slightly</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">vTheta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">atan2</span><span class="p">(</span><span class="nx">y</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">y</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="nx">perturbedV</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sin</span><span class="p">(</span><span class="nx">vTheta</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">perturbedV</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">cos</span><span class="p">(</span><span class="nx">vTheta</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> + +<span class="w"> </span><span class="c1">//console.log('Initial coords:', coords);</span><span class="w"></span> + + +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">masses</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="nx">nBodies</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="nx">Mp</span><span class="p">);</span><span class="w"> </span><span class="c1">// Initialize masses</span><span class="w"></span> +<span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">Mstar</span><span class="p">;</span><span class="w"> </span><span class="c1">// Make index one special as the central star</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">][</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">][</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="c1">// Initialize central star at origin with no velocity</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">yearSec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">365</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">3600</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">time</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="w"> </span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="nx">nTPts</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">(</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">tStop</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="p">(</span><span class="nx">nTPts</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">yearSec</span><span class="p">);</span><span class="w"> </span><span class="c1">// Years -> s</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">deltaT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">tInd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">coordsRecord</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">deepCopyCoordsArray</span><span class="p">(</span><span class="nx">coords</span><span class="p">)];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">massRecord</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">masses</span><span class="p">.</span><span class="nx">slice</span><span class="p">()];</span><span class="w"> </span><span class="c1">// Initialize records with initial conditions</span><span class="w"></span> + + +<span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="nx">tInd</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">nTPts</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">nBodies</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="nx">nBodiesStop</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="c1">//console.log('Initial coords:', coords);</span><span class="w"></span> +<span class="w"> </span><span class="p">[</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">nBodyStep</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="mf">10</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">1.5e11</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">);</span><span class="w"> </span><span class="c1">// Update</span><span class="w"></span> +<span class="w"> </span><span class="nx">coordsRecord</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">deepCopyCoordsArray</span><span class="p">(</span><span class="nx">coords</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="nx">massRecord</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">masses</span><span class="p">.</span><span class="nx">slice</span><span class="p">());</span><span class="w"> </span><span class="c1">// Add to records</span><span class="w"></span> +<span class="w"> </span><span class="nx">tInd</span><span class="o">++</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="nx">tInd</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="c1">//console.log(`currently at t = ${(t / yearSec).toFixed(2)} years\r`);</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="sb">`final time = </span><span class="si">${</span><span class="nx">time</span><span class="p">[</span><span class="nx">tInd</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">yearSec</span><span class="si">}</span><span class="sb"> years with </span><span class="si">${</span><span class="nx">nBodies</span><span class="si">}</span><span class="sb"> bodies remaining`</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="c1">// Set button text to Start Simulation</span><span class="w"></span> +<span class="w"> </span><span class="nx">btn</span><span class="p">.</span><span class="nx">innerHTML</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">prevText</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">coordsRecord</span><span class="p">,</span><span class="w"> </span><span class="nx">massRecord</span><span class="p">,</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">tInd</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">1</span><span class="p">)];</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + + +<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="p">[</span><span class="nx">coordsRecordR</span><span class="p">,</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">tR</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">genNBodyResults</span><span class="p">(</span><span class="mf">256</span><span class="p">,</span><span class="mf">1</span><span class="p">,</span><span class="mf">1001</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="c1">//console.log(coordsRecordR);</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">yearSec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">365</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">3600</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">createFrame</span><span class="p">(</span><span class="nx">coordsR</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">coordsR</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="o">!</span><span class="nx">coordsR</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="o">!</span><span class="nx">coordsR</span><span class="p">[</span><span class="mf">1</span><span class="p">])</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">[];</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> + +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">traceCentralStar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="nx">coordsR</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">1.5e11</span><span class="p">],</span><span class="w"></span> +<span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="nx">coordsR</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">1.5e11</span><span class="p">],</span><span class="w"></span> +<span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s1">'markers'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">type</span><span class="o">:</span><span class="w"> </span><span class="s1">'scatter'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s1">'Central star'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">marker</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">color</span><span class="o">:</span><span class="w"> </span><span class="s1">'gold'</span><span class="p">,</span><span class="w"> </span><span class="nx">symbol</span><span class="o">:</span><span class="w"> </span><span class="s1">'star'</span><span class="p">,</span><span class="w"> </span><span class="nx">size</span><span class="o">:</span><span class="w"> </span><span class="mf">10</span><span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="p">};</span><span class="w"></span> + +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">xCoords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coordsR</span><span class="p">[</span><span class="mf">0</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="mf">1</span><span class="p">).</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">1.5e11</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">yCoords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coordsR</span><span class="p">[</span><span class="mf">1</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="mf">1</span><span class="p">).</span><span class="nx">map</span><span class="p">(</span><span class="nx">y</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">1.5e11</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">traceOtherBodies</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nx">xCoords</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="nx">yCoords</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s1">'markers'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">type</span><span class="o">:</span><span class="w"> </span><span class="s1">'scatter'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s1">''</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">marker</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">color</span><span class="o">:</span><span class="w"> </span><span class="s1">'dodgerblue'</span><span class="p">,</span><span class="w"> </span><span class="nx">symbol</span><span class="o">:</span><span class="w"> </span><span class="s1">'circle'</span><span class="p">,</span><span class="w"> </span><span class="nx">size</span><span class="o">:</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="p">};</span><span class="w"></span> + +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">traceCentralStar</span><span class="p">,</span><span class="w"> </span><span class="nx">traceOtherBodies</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> + + +<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">createLayout</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">text</span><span class="o">:</span><span class="w"> </span><span class="sb">`N-Body Problem: t = </span><span class="si">${</span><span class="nb">Number</span><span class="p">(</span><span class="nx">t</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">yearSec</span><span class="p">).</span><span class="nx">toFixed</span><span class="p">(</span><span class="mf">3</span><span class="p">)</span><span class="si">}</span><span class="sb"> years`</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="mf">0.03</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="mf">0.97</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">xanchor</span><span class="o">:</span><span class="w"> </span><span class="s1">'left'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">yanchor</span><span class="o">:</span><span class="w"> </span><span class="s1">'top'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">font</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">size</span><span class="o">:</span><span class="w"> </span><span class="mf">14</span><span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="nx">xaxis</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s1">'x [AU]'</span><span class="p">,</span><span class="w"> </span><span class="nx">range</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mf">2.1</span><span class="p">,</span><span class="w"> </span><span class="mf">2.1</span><span class="p">]</span><span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="nx">yaxis</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s1">'y [AU]'</span><span class="p">,</span><span class="w"> </span><span class="nx">range</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mf">2.1</span><span class="p">,</span><span class="w"> </span><span class="mf">2.1</span><span class="p">],</span><span class="w"> </span><span class="nx">scaleanchor</span><span class="o">:</span><span class="w"> </span><span class="s1">'x'</span><span class="p">,</span><span class="w"> </span><span class="nx">scaleratio</span><span class="o">:</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="nx">showlegend</span><span class="o">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">margin</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">l</span><span class="o">:</span><span class="w"> </span><span class="mf">60</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="o">:</span><span class="w"> </span><span class="mf">40</span><span class="p">,</span><span class="w"> </span><span class="nx">t</span><span class="o">:</span><span class="w"> </span><span class="mf">40</span><span class="p">,</span><span class="w"> </span><span class="nx">b</span><span class="o">:</span><span class="w"> </span><span class="mf">40</span><span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="mf">800</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">height</span><span class="o">:</span><span class="w"> </span><span class="mf">800</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">plot_bgcolor</span><span class="o">:</span><span class="w"> </span><span class="s1">'black'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="p">};</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">animateNBodyProblem</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">nFrames</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">tR</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">nFrames</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">frameData</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createFrame</span><span class="p">(</span><span class="nx">coordsRecordR</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">layout</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createLayout</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="c1">//Plotly.newPlot(plotDiv, frameData, layout);</span><span class="w"></span> +<span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">Plotly</span><span class="p">.</span><span class="nx">animate</span><span class="p">(</span><span class="s2">"plot"</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">data</span><span class="o">:</span><span class="w"> </span><span class="nx">frameData</span><span class="p">,</span><span class="w"> </span><span class="nx">layout</span><span class="o">:</span><span class="w"> </span><span class="nx">layout</span><span class="w"></span> +<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">staticPlot</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">transition</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">duration</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="nx">frame</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">duration</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">redraw</span><span class="o">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="p">});</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">Plotly</span><span class="p">.</span><span class="nx">newPlot</span><span class="p">(</span><span class="s1">'plot'</span><span class="p">,</span><span class="w"> </span><span class="nx">frameData</span><span class="p">,</span><span class="w"> </span><span class="nx">layout</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="nx">animateNBodyProblem</span><span class="p">();</span><span class="w"></span> +</code></pre> +</div> + +<h2>Playground</h2> + +<script src="https://cdn.plot.ly/plotly-latest.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/11.8.0/math.js"></script> +<script src="/assets/n-body/script.js"></script> +<div id="main-plot-div"> +<div id="plot"></div> + +<label for="speedControl">Speed for 3-Body Visualisation</label> +<input type="range" min="1" max="20" value="10" id="speedControl"> +<label for="nBodies">Number of Bodies for n-Body Simulation (5-500)</label> +<input type="range" min="5" max="500" value="256" id="nBodies"> +</div> +<button type="button" id="startSim1" onclick="plotEarthSun()">Sun-Earth Orbit</button> +<button type="button" id="startSim2" onclick="plotClassic3BodyProblem()">Classic 3-Body Problem</button> +<button type="button" id="startSim3" onclick="plotRandom3BodySimulation()">Random n-Body Simulation</button> +<script> +function clearAl() { + plotOrbit = false; + plotClassic = false; + plotRandom = false; +} + +function plotEarthSun() { + clearAl(); + plotOrbit = true; + calculateAndPlot(); + setTimeout(function(){ + calculateAndPlot() + }, 500); + } + +function plotClassic3BodyProblem() { + clearAl(); + plotClassic = true; + calculateAndPlot(); + setTimeout(function(){ + calculateAndPlot() + }, 500); + } + +function plotRandom3BodySimulation() { + clearAl(); + plotRandom = true; + calculateAndPlot(); + } + + +</script> + +<script> + document.getElementById("speedControl").addEventListener("input", (event) => { + const speedPercentage = parseInt(event.target.value, 10); + delay = speedPercentage; // Adjust the delay based on the trackbar value +}); + document.getElementById("nBodies").addEventListener("input", (event) => { + nBodies = parseInt(event.target.value, 10); + }); + + </script> + <noscript> This post requires JavaScript to be viewed properly :( </noscript> diff --git a/docs/posts/2023-04-30-n-body-simulation.html b/docs/posts/2023-04-30-n-body-simulation.html index 02df562..302e2e0 100644 --- a/docs/posts/2023-04-30-n-body-simulation.html +++ b/docs/posts/2023-04-30-n-body-simulation.html @@ -58,6 +58,692 @@ <p>This post requires JavaScript to be viewed properly :(</p> +<p>Adapted from the Numerics Tutorial - <a rel="noopener" target="_blank" href="https://github.com/kirklong/ThreeBodyBot/tree/master/NumericsTutorial">kirklong/ThreeBodyBot</a>. The Julia code has been rewritten in JavaScript.</p> + +<p>Workflow:</p> + +<ul> +<li><p>Understand the problem</p></li> +<li><p>Visualise a basic orbit</p></li> +<li><p>Solve and plot the classic figure-8 orbit</p></li> +<li><p>random n-body solution generator</p></li> +</ul> + +<p><strong>To workaround memory issues, the simulations are only run on-demand when the user clicks the respective button. Scroll down to the bottom of the page to see the results.</strong></p> + +<h2>The n-body problem</h2> + +<p>The n-body problem is a classic puzzle in physics (and thus astrophysics) and mathematics that deals with predicting the motion of multiple celestial objects that interact with each other through gravitational forces. </p> + +<p>Imagine you are observing a <em>cosmic dance</em> between multiple celestial bodies, all tugging on one another as they move through space. The n-body problem aims to undersand and predict the paths of these objects as they move through space.</p> + +<p>When <code>n=2</code>, i.e we have only two objects, say the Earth and the Moon, we can easily apply Newtonian physics to predict their motion. However, when <code>n>2</code>, the problem becomes much more difficult to solve analytically. This is because each object feels the gravitational pull from all other objects, and thus the equations of motion become coupled and non-linear. </p> + +<p>As the number of objects increases, finding an exact solution becomes impossible, and we rely on analyticals approximations.</p> + +<h2>Visualising a basic orbit</h2> + +<p>If we want to create a n-body simulation in our browser, we need to figure out how we are going to visualise the motion of the objects. There are a few ways to do this, but the easiest is to use Plotly.js, a JavaScript library for creating interactive graphs. (An alternative is to use the HTML5 canvas element).</p> + +<div class="codehilite"> +<pre><span></span><code><span class="cm">/*</span> +<span class="cm"> * Earth - Sun Orbit Plot</span> +<span class="cm"> * Taken from Numerics tutorial</span> +<span class="cm"> */</span><span class="w"></span> + +<span class="kd">const</span><span class="w"> </span><span class="nx">G</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">6.67e-11</span><span class="p">;</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">Msun</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">2e30</span><span class="p">;</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">AU</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1.5e11</span><span class="p">;</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">v0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sqrt</span><span class="p">(</span><span class="nx">G</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">Msun</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">AU</span><span class="p">);</span><span class="w"> </span><span class="c1">// SI</span><span class="w"></span> + +<span class="kd">function</span><span class="w"> </span><span class="nx">dR</span><span class="p">(</span><span class="nx">r</span><span class="p">,</span><span class="w"> </span><span class="nx">v</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">dv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="nx">G</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">Msun</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">3</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="mf">0</span><span class="p">],</span><span class="w"> </span><span class="o">-</span><span class="nx">G</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">Msun</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">3</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="mf">1</span><span class="p">]];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">dr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[...</span><span class="nx">v</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">dr</span><span class="p">,</span><span class="w"> </span><span class="nx">dv</span><span class="p">];</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="c1">// initialize system</span><span class="w"></span> +<span class="kd">let</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="nx">AU</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">];</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">theta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">atan2</span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="mf">1</span><span class="p">],</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="mf">0</span><span class="p">]);</span><span class="w"></span> +<span class="kd">let</span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="nx">v0</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sin</span><span class="p">(</span><span class="nx">theta</span><span class="p">),</span><span class="w"> </span><span class="nx">v0</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">cos</span><span class="p">(</span><span class="nx">theta</span><span class="p">)];</span><span class="w"></span> + +<span class="kd">const</span><span class="w"> </span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="w"> </span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="mf">1001</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">(</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">100</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">0.0</span><span class="p">);</span><span class="w"> </span><span class="c1">// years</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">yearSec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">365</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">3600</span><span class="p">;</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">dt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">t</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">t</span><span class="p">[</span><span class="mf">0</span><span class="p">])</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">yearSec</span><span class="p">;</span><span class="w"> </span><span class="c1">// s</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">x4Plot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="w"> </span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="nx">t</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="mf">0</span><span class="p">);</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">y4Plot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="w"> </span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="nx">t</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="mf">0</span><span class="p">);</span><span class="w"></span> + +<span class="c1">// integrate using RK4!</span><span class="w"></span> +<span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">t</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">k1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">dR</span><span class="p">(</span><span class="nx">r</span><span class="p">,</span><span class="w"> </span><span class="nx">v</span><span class="p">).</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">y</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">dt</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">k2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">dR</span><span class="p">(</span><span class="nx">r</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">ri</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">ri</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k1</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">2</span><span class="p">),</span><span class="w"> </span><span class="nx">v</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">vi</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">vi</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k1</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">2</span><span class="p">)).</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">y</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">dt</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">k3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">dR</span><span class="p">(</span><span class="nx">r</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">ri</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">ri</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k2</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">2</span><span class="p">),</span><span class="w"> </span><span class="nx">v</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">vi</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">vi</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k2</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">2</span><span class="p">)).</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">y</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">dt</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">k4</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">dR</span><span class="p">(</span><span class="nx">r</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">ri</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">ri</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k3</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">j</span><span class="p">]),</span><span class="w"> </span><span class="nx">v</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">vi</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">vi</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k3</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">j</span><span class="p">])).</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">y</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">dt</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">ri</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">ri</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">k1</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">k2</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">k3</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k4</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">j</span><span class="p">])</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">6</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">v</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">vi</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">vi</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">k1</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">k2</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">k3</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k4</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">j</span><span class="p">])</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">6</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">x4Plot</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="nx">y4Plot</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="mf">1</span><span class="p">];</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="c1">// make data for plot</span><span class="w"></span> +<span class="kd">var</span><span class="w"> </span><span class="nx">sun</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="p">};</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">earth</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nx">x4Plot</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">AU</span><span class="p">),</span><span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="nx">y4Plot</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">y</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">AU</span><span class="p">)</span><span class="w"> </span><span class="p">};</span><span class="w"></span> +<span class="kd">const</span><span class="w"> </span><span class="nx">circle</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="w"> </span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="mf">1001</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">(</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">cos</span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">100</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">PI</span><span class="p">)),</span><span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="w"> </span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="mf">1001</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">(</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sin</span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">100</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">PI</span><span class="p">))</span><span class="w"> </span><span class="p">};</span><span class="w"></span> +</code></pre> +</div> + +<p>This code simulates the orbit of Earth around the Sun, using a numerical method called the Runge-Kutta 4th order (RK4) method.</p> + +<p>First, we define some constants:</p> + +<p>G: the gravitational constant (6.67e-11 N m²/kg²) +Msun: the mass of the Sun (2e30 kg) +AU: an astronomical unit, the average distance between Earth and Sun (1.5e11 m) +v0: the initial velocity of Earth, calculated from its distance to the Sun +Next, the function dR takes the position r and velocity v of Earth as input and returns the rate of change in position (dr) and the rate of change in velocity (dv) using the gravitational force formula.</p> + +<p>We then initialize the position r and velocity v of Earth, and create an array t that represents time in years, divided into 1001 steps. We also define yearSec as the number of seconds in a year and dt as the time step in seconds.</p> + +<p>Now, we integrate the Earth's motion using the RK4 method. For each time step, we calculate the rates of change for position and velocity (k1, k2, k3, k4) and update Earth's position and velocity based on these. We store the updated position in x4Plot and y4Plot.</p> + +<p>Finally, we normalize the position data by dividing it by the astronomical unit (AU) to make it more visually meaningful. We also create a circle for reference, which represents a perfect circular orbit. The code ends with the data for the Sun's position, Earth's orbit, and the reference circle ready to be plotted.</p> + +<h3>Plotting the orbit</h3> + +<p>Now that we have the data for the Sun's position, Earth's orbit, and the reference circle, we can plot them using Plotly.js. + <div class="codehilite"> + <pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="nx">traceSun</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="nx">sun</span><span class="p">.</span><span class="nx">x</span><span class="p">],</span><span class="w"></span> + <span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="nx">sun</span><span class="p">.</span><span class="nx">y</span><span class="p">],</span><span class="w"></span> + <span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s2">"markers"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">marker</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">symbol</span><span class="o">:</span><span class="w"> </span><span class="s2">"star"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">size</span><span class="o">:</span><span class="w"> </span><span class="mf">10</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">color</span><span class="o">:</span><span class="w"> </span><span class="s2">"gold"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s2">"Sun"</span><span class="p">,</span><span class="w"></span> + <span class="p">};</span><span class="w"></span> + <br /> + <span class="kd">const</span><span class="w"> </span><span class="nx">traceEarth</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nx">earth</span><span class="p">.</span><span class="nx">x</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="nx">earth</span><span class="p">.</span><span class="nx">y</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s2">"lines"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">color</span><span class="o">:</span><span class="w"> </span><span class="s2">"white"</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s2">"Earth"</span><span class="p">,</span><span class="w"></span> + <span class="p">};</span><span class="w"></span> + <br /> + <span class="kd">const</span><span class="w"> </span><span class="nx">traceOrbit</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nx">circle</span><span class="p">.</span><span class="nx">x</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="nx">circle</span><span class="p">.</span><span class="nx">y</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s2">"lines"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">color</span><span class="o">:</span><span class="w"> </span><span class="s2">"crimson"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">dash</span><span class="o">:</span><span class="w"> </span><span class="s2">"dash"</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s2">"1 AU Circle"</span><span class="p">,</span><span class="w"></span> + <span class="p">};</span><span class="w"></span> + <br /> + <span class="kd">const</span><span class="w"> </span><span class="nx">earthSunLayout</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s2">"Earth-Sun Orbit"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">xaxis</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s2">"x [AU]"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">range</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mf">1.1</span><span class="p">,</span><span class="mf">1.1</span><span class="p">],</span><span class="w"></span> + <span class="w"> </span><span class="nx">showgrid</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">gridcolor</span><span class="o">:</span><span class="w"> </span><span class="s2">"rgba(255,255,255,0.5)"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">gridwidth</span><span class="o">:</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">zeroline</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">tickmode</span><span class="o">:</span><span class="w"> </span><span class="s2">"auto"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">nticks</span><span class="o">:</span><span class="w"> </span><span class="mf">5</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">yaxis</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s2">"y [AU]"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">range</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mf">1.1</span><span class="p">,</span><span class="mf">1.1</span><span class="p">],</span><span class="w"></span> + <span class="w"> </span><span class="nx">showgrid</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">gridcolor</span><span class="o">:</span><span class="w"> </span><span class="s2">"rgba(255,255,255,0.5)"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">gridwidth</span><span class="o">:</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">zeroline</span><span class="o">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">tickmode</span><span class="o">:</span><span class="w"> </span><span class="s2">"auto"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">nticks</span><span class="o">:</span><span class="w"> </span><span class="mf">5</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">margin</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">l</span><span class="o">:</span><span class="w"> </span><span class="mf">50</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">r</span><span class="o">:</span><span class="w"> </span><span class="mf">50</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">b</span><span class="o">:</span><span class="w"> </span><span class="mf">50</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">t</span><span class="o">:</span><span class="w"> </span><span class="mf">50</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">pad</span><span class="o">:</span><span class="w"> </span><span class="mf">4</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">paper<em>bgcolor</span><span class="o">:</span><span class="w"> </span><span class="s2">"black"</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">plot</em>bgcolor</span><span class="o">:</span><span class="w"> </span><span class="s2">"black"</span><span class="p">,</span><span class="w"></span> + <span class="p">};</span><span class="w"></span> + <span class="nx">Plotly</span><span class="p">.</span><span class="nx">newPlot</span><span class="p">(</span><span class="s2">"plot"</span><span class="p">,[</span><span class="nx">traceSun</span><span class="p">,</span><span class="nx">traceEarth</span><span class="p">,</span><span class="nx">traceOrbit</span><span class="p">],</span><span class="w"> </span><span class="nx">earthSunLayout</span><span class="p">);</span><span class="w"></span> + </code></pre> + </div></p> + +<h2>Figure of 8 orbit</h2> + +<p>The figure of 8 solution in the three-body problem refers to a unique and special trajectory where three celestial bodies (e.g., planets, stars) move in a figure of 8 shaped pattern around their mutual center of mass. This is special because it represents a stable and periodic solution to the three-body problem, which is known for its complexity and lack of general solutions.</p> + +<p>In the figure of 8 solution, each of the three bodies follows the same looping path, but with a phase difference such that when one body is at one end of the loop, the other two are symmetrically positioned elsewhere along the path. The bodies maintain equal distances from each other throughout their motion, and their velocities and positions are perfectly balanced to maintain this periodic motion.</p> + +<p>The figure of 8 is interesting because:</p> + +<ul> +<li><p>It is a relatively stable solution, which means that the objects continue to follow the same looping path almost indefinitely.</p></li> +<li><p>It breaks down the notion that no simple periodic solutions exist for the three-body problem.</p></li> +<li><p>It looks cool!</p></li> +</ul> + +<h3>Show me the code</h3> + +<p>The code for this simulation is very similar to the Earth-Sun orbit simulation, except that we now have three bodies instead of two. We also use a different set of initial conditions to generate the figure of 8 orbit.</p> + +<div class="codehilite"> +<pre><span></span><code><span class="kd">function</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">vx</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">vy</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">];</span><span class="w"></span> + +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">delta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">clone</span><span class="p">(</span><span class="nx">coords</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">;</span><span class="w"> </span><span class="nx">n</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">xn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">n</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">yn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">y</span><span class="p">[</span><span class="nx">n</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">deltaVx</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.0</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">deltaVy</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.0</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="nx">n</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">sep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sqrt</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">xn</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">yn</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">y</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span><span class="w"> </span><span class="mf">2</span><span class="p">));</span><span class="w"> </span><span class="c1">// Euclidean distance</span><span class="w"></span> +<span class="w"> </span><span class="nx">deltaVx</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="nx">G</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="nx">xn</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">sep</span><span class="p">,</span><span class="w"> </span><span class="mf">3</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">deltaVy</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="nx">G</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="nx">yn</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">y</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">sep</span><span class="p">,</span><span class="w"> </span><span class="mf">3</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> + +<span class="w"> </span><span class="nx">delta</span><span class="p">[</span><span class="mf">2</span><span class="p">][</span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">deltaVx</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">delta</span><span class="p">[</span><span class="mf">3</span><span class="p">][</span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">deltaVy</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> + +<span class="w"> </span><span class="nx">delta</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">vx</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">delta</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">vy</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">delta</span><span class="p">;</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="kd">function</span><span class="w"> </span><span class="nx">step</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">6.67408313131313e-11</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">k1</span><span class="p">,</span><span class="w"> </span><span class="mf">0.5</span><span class="p">)),</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">k2</span><span class="p">,</span><span class="w"> </span><span class="mf">0.5</span><span class="p">)),</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k4</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">k3</span><span class="p">),</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> + +<span class="w"> </span><span class="nx">coords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">k1</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="mf">2.0</span><span class="p">,</span><span class="w"> </span><span class="nx">k2</span><span class="p">),</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="mf">2.0</span><span class="p">,</span><span class="w"> </span><span class="nx">k3</span><span class="p">),</span><span class="w"> </span><span class="nx">k4</span><span class="p">),</span><span class="w"> </span><span class="mf">1</span><span class="o">/</span><span class="mf">6</span><span class="p">));</span><span class="w"></span> + +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">coords</span><span class="p">;</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="w"> </span><span class="c1">// Initial conditions setup</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">M</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mf">0.97000436</span><span class="p">,</span><span class="w"> </span><span class="mf">0.0</span><span class="p">,</span><span class="w"> </span><span class="mf">0.97000436</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mf">0.24208753</span><span class="p">,</span><span class="w"> </span><span class="mf">0.0</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">0.24208753</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">vx</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mf">0.4662036850</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">0.933240737</span><span class="p">,</span><span class="w"> </span><span class="mf">0.4662036850</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">vy</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mf">0.4323657300</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">0.86473146</span><span class="p">,</span><span class="w"> </span><span class="mf">0.4323657300</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">Ei</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mf">1</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sqrt</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">0.97000436</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">0.24208753</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">))</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sqrt</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="mf">0.97000436</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="mf">0.24208753</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">0.5</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">sum</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">dotPow</span><span class="p">(</span><span class="nx">vx</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">),</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">dotPow</span><span class="p">(</span><span class="nx">vy</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">))));</span><span class="w"></span> + +<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">linspace</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span><span class="w"> </span><span class="nx">stop</span><span class="p">,</span><span class="w"> </span><span class="nx">num</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">step</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">stop</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">start</span><span class="p">)</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="p">(</span><span class="nx">num</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="nx">num</span><span class="p">},</span><span class="w"> </span><span class="p">(</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">start</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">step</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">i</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> + +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">coords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="p">,</span><span class="w"> </span><span class="nx">vx</span><span class="p">,</span><span class="w"> </span><span class="nx">vy</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">time</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">linspace</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">6.3259</span><span class="p">,</span><span class="w"> </span><span class="mf">1001</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">deltaT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span><span class="w"></span> + +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">X</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">zeros</span><span class="p">(</span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">length</span><span class="p">).</span><span class="nx">toArray</span><span class="p">();</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">Y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">zeros</span><span class="p">(</span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">length</span><span class="p">).</span><span class="nx">toArray</span><span class="p">();</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">VX</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">zeros</span><span class="p">(</span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">length</span><span class="p">).</span><span class="nx">toArray</span><span class="p">();</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">VY</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">zeros</span><span class="p">(</span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">length</span><span class="p">).</span><span class="nx">toArray</span><span class="p">();</span><span class="w"></span> + +<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">step</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">M</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">X</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">idx</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">X</span><span class="p">[</span><span class="nx">idx</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">idx</span><span class="p">]);</span><span class="w"></span> +<span class="w"> </span><span class="nx">Y</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">idx</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">Y</span><span class="p">[</span><span class="nx">idx</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">idx</span><span class="p">]);</span><span class="w"></span> +<span class="w"> </span><span class="nx">VX</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">idx</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">VX</span><span class="p">[</span><span class="nx">idx</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">][</span><span class="nx">idx</span><span class="p">]);</span><span class="w"></span> +<span class="w"> </span><span class="nx">VY</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">idx</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">VY</span><span class="p">[</span><span class="nx">idx</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">][</span><span class="nx">idx</span><span class="p">]);</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +</code></pre> +</div> + +<p>The <code>deltaR</code> function computes the rate of change in position and velocity of the celestial bodies based on their current positions, velocities, and masses. It accounts for the gravitational forces between all bodies.</p> + +<p>The <code>step</code> function performs a single RK4 integration step, updating the positions and velocities of the celestial bodies. It uses <code>deltaR</code> to compute the four increments (k1, k2, k3, and k4) and then updates the coordinates accordingly.</p> + +<p>Next, the initial conditions for the figure-8 three-body problem are set. The masses (<code>M</code>), initial positions (<code>x</code>, <code>y</code>), and initial velocities (<code>vx</code>, <code>vy</code>) are provided. <code>Ei</code> calculates the initial total energy of the system.</p> + +<p>The <code>linspace</code> function is defined to create a linearly spaced array of time points. <code>coords</code> is an array containing the positions and velocities for all bodies. The <code>time</code> array is created using <code>linspace</code>, and <code>deltaT</code> is set as the time step.</p> + +<p><code>X</code>, <code>Y</code>, <code>VX</code>, and <code>VY</code> are 2D arrays that will store the positions and velocities of the celestial bodies over time. They are initialized with zeros and will be updated in the loop.</p> + +<p>Finally, a loop iterates over each time step, updating the positions and velocities of the celestial bodies using the <code>step</code> function. The updated coordinates are stored in the <code>X</code>, <code>Y</code>, <code>VX</code>, and <code>VY</code> arrays.</p> + +<h3>Animation?</h3> + +<p>Now that we have time-series data, we need to animate it. We can use Plotly's animate function, as this does not force a full re-render, saving us some precious GPU and CPU cycles when we are trying to run this in the browser itself + <div class="codehilite"> + <pre><span></span><code><span class="kd">function</span><span class="w"> </span><span class="nx">plotClassicFunc</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">tailLength</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span><span class="w"></span> + <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">plotIndex</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">tailLength</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">tailLength</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">plotIndex</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">plotIndex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">tailLength</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">plotIndex</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">tailLength</span><span class="p">;</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"></span> + <br /> + <span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">currentIndex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">plotIndex</span><span class="p">;</span><span class="w"></span> + <br /> + <span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="nx">currentIndex</span><span class="p">].</span><span class="nx">toFixed</span><span class="p">(</span><span class="mf">3</span><span class="p">);</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="nx">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">currentIndex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"></span> + <br /> + <span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="w"></span> + <span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nx">X</span><span class="p">[</span><span class="mf">0</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="nx">tailLength</span><span class="p">,</span><span class="w"> </span><span class="nx">currentIndex</span><span class="p">),</span><span class="w"></span> + <span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="nx">Y</span><span class="p">[</span><span class="mf">0</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="nx">tailLength</span><span class="p">,</span><span class="w"> </span><span class="nx">currentIndex</span><span class="p">),</span><span class="w"></span> + <span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s1">'lines+markers'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">marker</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">symbol</span><span class="o">:</span><span class="w"> </span><span class="s1">'star'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">size</span><span class="o">:</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s1">''</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nx">X</span><span class="p">[</span><span class="mf">1</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="nx">tailLength</span><span class="p">,</span><span class="w"> </span><span class="nx">currentIndex</span><span class="p">),</span><span class="w"></span> + <span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="nx">Y</span><span class="p">[</span><span class="mf">1</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="nx">tailLength</span><span class="p">,</span><span class="w"> </span><span class="nx">currentIndex</span><span class="p">),</span><span class="w"></span> + <span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s1">'lines+markers'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">marker</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">symbol</span><span class="o">:</span><span class="w"> </span><span class="s1">'star'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">size</span><span class="o">:</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s1">''</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nx">X</span><span class="p">[</span><span class="mf">2</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="nx">tailLength</span><span class="p">,</span><span class="w"> </span><span class="nx">currentIndex</span><span class="p">),</span><span class="w"></span> + <span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="nx">Y</span><span class="p">[</span><span class="mf">2</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="nx">tailLength</span><span class="p">,</span><span class="w"> </span><span class="nx">currentIndex</span><span class="p">),</span><span class="w"></span> + <span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s1">'lines+markers'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">marker</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">symbol</span><span class="o">:</span><span class="w"> </span><span class="s1">'star'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">size</span><span class="o">:</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s1">''</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="p">];</span><span class="w"></span> + <br /> + <span class="c1">// width: 1000, height: 400</span><span class="w"></span> + <span class="kd">const</span><span class="w"> </span><span class="nx">layout</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s1">'∞ Three-Body Problem: t = '</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="nx">currentIndex</span><span class="p">].</span><span class="nx">toFixed</span><span class="p">(</span><span class="mf">3</span><span class="p">),</span><span class="w"></span> + <span class="w"> </span><span class="nx">xaxis</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s1">'x'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">range</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mf">1.1</span><span class="p">,</span><span class="mf">1.1</span><span class="p">]</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">yaxis</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s1">'y'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">scaleanchor</span><span class="o">:</span><span class="w"> </span><span class="s1">'x'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">scaleratio</span><span class="o">:</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">range</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mf">0.5</span><span class="p">,</span><span class="mf">0.5</span><span class="p">]</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">plot<em>bgcolor</span><span class="o">:</span><span class="w"> </span><span class="s1">'black'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">paper</em>bgcolor</span><span class="o">:</span><span class="w"> </span><span class="s1">'black'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">font</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">color</span><span class="o">:</span><span class="w"> </span><span class="s1">'white'</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="p">};</span><span class="w"></span> + <br /> + <span class="k">try</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="nx">Plotly</span><span class="p">.</span><span class="nx">animate</span><span class="p">(</span><span class="s2">"plot"</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">data</span><span class="o">:</span><span class="w"> </span><span class="nx">data</span><span class="p">,</span><span class="w"> </span><span class="nx">layout</span><span class="o">:</span><span class="w"> </span><span class="nx">layout</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">staticPlot</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">transition</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">duration</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">},</span><span class="w"></span> + <span class="w"> </span><span class="nx">frame</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">duration</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="nx">redraw</span><span class="o">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"></span> + <span class="w"> </span><span class="p">});</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">Plotly</span><span class="p">.</span><span class="nx">newPlot</span><span class="p">(</span><span class="s1">'plot'</span><span class="p">,</span><span class="w"> </span><span class="nx">data</span><span class="p">,</span><span class="w"> </span><span class="nx">layout</span><span class="p">);</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"></span> + <br /> + <br /> + <span class="nx">plotIndex</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">delay</span><span class="p">;</span><span class="w"></span> + <span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">plotClassic</span><span class="o">===</span><span class="kc">true</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">requestAnimationFrame</span><span class="p">(</span><span class="nx">plotClassicFunc</span><span class="p">);</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"></span> + <span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + <span class="w"> </span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w"></span> + <span class="w"> </span><span class="p">}</span><span class="w"></span> + <span class="p">}</span><span class="w"></span> + <br /> + <span class="p">}</span><span class="w"></span> + </code></pre> + </div></p> + +<h2>"General" N-Body Solver</h2> + +<h3>Show me the code!</h3> + +<div class="codehilite"> +<pre><span></span><code><span class="kd">function</span><span class="w"> </span><span class="nx">step</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">6.67408313131313e-11</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">k1</span><span class="p">,</span><span class="w"> </span><span class="mf">0.5</span><span class="p">)),</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">k2</span><span class="p">,</span><span class="w"> </span><span class="mf">0.5</span><span class="p">)),</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">k4</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaR</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">k3</span><span class="p">),</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">));</span><span class="w"></span> + +<span class="w"> </span><span class="nx">coords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">k1</span><span class="p">,</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="mf">2.0</span><span class="p">,</span><span class="w"> </span><span class="nx">k2</span><span class="p">),</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">multiply</span><span class="p">(</span><span class="mf">2.0</span><span class="p">,</span><span class="w"> </span><span class="nx">k3</span><span class="p">),</span><span class="w"> </span><span class="nx">k4</span><span class="p">),</span><span class="w"> </span><span class="mf">1</span><span class="o">/</span><span class="mf">6</span><span class="p">));</span><span class="w"></span> + +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">coords</span><span class="p">;</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="kd">function</span><span class="w"> </span><span class="nx">detectCollisionsEscape</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">maxSep</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="p">,</span><span class="w"> </span><span class="nx">vx</span><span class="p">,</span><span class="w"> </span><span class="nx">vy</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coords</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">V</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">vx</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">v</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sqrt</span><span class="p">(</span><span class="nx">v</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">vy</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">R</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">V</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">v</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">collision</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="nx">collisionInds</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="nx">escape</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="nx">escapeInd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">n</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">rn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">R</span><span class="p">[</span><span class="nx">n</span><span class="p">],</span><span class="w"> </span><span class="nx">xn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">n</span><span class="p">],</span><span class="w"> </span><span class="nx">yn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">y</span><span class="p">[</span><span class="nx">n</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="nx">n</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">minSep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">rn</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">R</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">sep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sqrt</span><span class="p">((</span><span class="nx">xn</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">yn</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">y</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">sep</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">minSep</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">collision</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">collisionInds</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">sep</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="nx">maxSep</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">escape</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">escapeInd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">n</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">collision</span><span class="p">,</span><span class="w"> </span><span class="nx">collisionInds</span><span class="p">,</span><span class="w"> </span><span class="nx">escape</span><span class="p">,</span><span class="w"> </span><span class="nx">escapeInd</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">collision</span><span class="p">,</span><span class="w"> </span><span class="nx">collisionInds</span><span class="p">,</span><span class="w"> </span><span class="nx">escape</span><span class="p">,</span><span class="w"> </span><span class="nx">escapeInd</span><span class="p">];</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="kd">function</span><span class="w"> </span><span class="nx">nBodyStep</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">maxSep</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">6.67408313131313e-11</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// Similar to our step function before, but keeping track of collisions</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">step</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">);</span><span class="w"> </span><span class="c1">// Update the positions as we did before</span><span class="w"></span> +<span class="w"> </span><span class="c1">//console.log(detectCollisionsEscape(coords, deltaT, maxSep));</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="nx">collision</span><span class="p">,</span><span class="w"> </span><span class="nx">collisionInds</span><span class="p">,</span><span class="w"> </span><span class="nx">escape</span><span class="p">,</span><span class="w"> </span><span class="nx">escapeInd</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">detectCollisionsEscape</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="nx">maxSep</span><span class="p">);</span><span class="w"> </span><span class="c1">// Detect collisions/escapes</span><span class="w"></span> + + +<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">collision</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// Do inelastic collision and delete extra body (2 -> 1)</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">i1</span><span class="p">,</span><span class="w"> </span><span class="nx">i2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">collisionInds</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">x1</span><span class="p">,</span><span class="w"> </span><span class="nx">x2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">i1</span><span class="p">],</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">i2</span><span class="p">]];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">y1</span><span class="p">,</span><span class="w"> </span><span class="nx">y2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">i1</span><span class="p">],</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">i2</span><span class="p">]];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">vx1</span><span class="p">,</span><span class="w"> </span><span class="nx">vx2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">][</span><span class="nx">i1</span><span class="p">],</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">][</span><span class="nx">i2</span><span class="p">]];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">vy1</span><span class="p">,</span><span class="w"> </span><span class="nx">vy2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">][</span><span class="nx">i1</span><span class="p">],</span><span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">][</span><span class="nx">i2</span><span class="p">]];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">px1</span><span class="p">,</span><span class="w"> </span><span class="nx">px2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">vx1</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i2</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">vx2</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">py1</span><span class="p">,</span><span class="w"> </span><span class="nx">py2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">vy1</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i2</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">vy2</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">px</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">px1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">px2</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">py</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">py1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">py2</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">newM</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i2</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">vfx</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">px</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">newM</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">vfy</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">py</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">newM</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">x1</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">x2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i2</span><span class="p">])</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="p">(</span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i2</span><span class="p">]);</span><span class="w"> </span><span class="c1">// Center of mass</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">y1</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">y2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i2</span><span class="p">])</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="p">(</span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i2</span><span class="p">]);</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">][</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">vfx</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">][</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">vfy</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">].</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i2</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">].</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i2</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">].</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i2</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">].</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i2</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">newM</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">masses</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i2</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">nBodies</span><span class="o">--</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="c1">// Could also implement condition for escape where we stop calculating forces but I'm too lazy for now</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">collision</span><span class="p">,</span><span class="w"> </span><span class="nx">collisionInds</span><span class="p">,</span><span class="w"> </span><span class="nx">escape</span><span class="p">,</span><span class="w"> </span><span class="nx">escapeInd</span><span class="p">];</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="kd">function</span><span class="w"> </span><span class="nx">uniform</span><span class="p">(</span><span class="nx">min</span><span class="p">,</span><span class="w"> </span><span class="nx">max</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="nx">max</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">min</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">min</span><span class="p">;</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="kd">function</span><span class="w"> </span><span class="nx">deepCopyCoordsArray</span><span class="p">(</span><span class="nx">arr</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">arr</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">innerArr</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">innerArr</span><span class="p">.</span><span class="nx">slice</span><span class="p">());</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="kd">function</span><span class="w"> </span><span class="nx">genNBodyResults</span><span class="p">(</span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">tStop</span><span class="p">,</span><span class="w"> </span><span class="nx">nTPts</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodiesStop</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">10</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">6.67408313131313e-11</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> + +<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">btn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">"startSim3"</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="c1">// Set button text to Solving</span><span class="w"></span> +<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">prevText</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">btn</span><span class="p">.</span><span class="nx">innerHTML</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">btn</span><span class="p">.</span><span class="nx">innerHTML</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Solving..."</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">coords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nb">Array</span><span class="p">(</span><span class="nx">nBodies</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="mf">0</span><span class="p">),</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="nx">nBodies</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="mf">0</span><span class="p">),</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="nx">nBodies</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="mf">0</span><span class="p">),</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="nx">nBodies</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="mf">0</span><span class="p">)];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">Mstar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">2e30</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">Mp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">Mstar</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">1e4</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// Initialize coordinates on ~Keplerian orbits</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">accept</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">accept</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// Prevent a particle from spawning within 0.2 AU too close to "star"</span><span class="w"></span> +<span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">1.5e11</span><span class="p">;</span><span class="w"> </span><span class="c1">// Say radius of 2 AU</span><span class="w"></span> +<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">1.5e11</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0.2</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">accept</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">theta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">uniform</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">PI</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">cos</span><span class="p">(</span><span class="nx">theta</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sin</span><span class="p">(</span><span class="nx">theta</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sqrt</span><span class="p">(</span><span class="nx">G</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">Mstar</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">r</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">perturbedV</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">1000</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">uniform</span><span class="p">(</span><span class="o">-</span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span><span class="w"> </span><span class="c1">// Perturb the velocities ever so slightly</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">vTheta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">atan2</span><span class="p">(</span><span class="nx">y</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">y</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="nx">perturbedV</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">sin</span><span class="p">(</span><span class="nx">vTheta</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">][</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">perturbedV</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">cos</span><span class="p">(</span><span class="nx">vTheta</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> + +<span class="w"> </span><span class="c1">//console.log('Initial coords:', coords);</span><span class="w"></span> + + +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">masses</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="nx">nBodies</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="nx">Mp</span><span class="p">);</span><span class="w"> </span><span class="c1">// Initialize masses</span><span class="w"></span> +<span class="w"> </span><span class="nx">masses</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">Mstar</span><span class="p">;</span><span class="w"> </span><span class="c1">// Make index one special as the central star</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">2</span><span class="p">][</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">coords</span><span class="p">[</span><span class="mf">3</span><span class="p">][</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="c1">// Initialize central star at origin with no velocity</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">yearSec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">365</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">3600</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">time</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="w"> </span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="nx">nTPts</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">(</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">tStop</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="p">(</span><span class="nx">nTPts</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">yearSec</span><span class="p">);</span><span class="w"> </span><span class="c1">// Years -> s</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">deltaT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">tInd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">coordsRecord</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">deepCopyCoordsArray</span><span class="p">(</span><span class="nx">coords</span><span class="p">)];</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">massRecord</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">masses</span><span class="p">.</span><span class="nx">slice</span><span class="p">()];</span><span class="w"> </span><span class="c1">// Initialize records with initial conditions</span><span class="w"></span> + + +<span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="nx">tInd</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">nTPts</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">nBodies</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="nx">nBodiesStop</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="c1">//console.log('Initial coords:', coords);</span><span class="w"></span> +<span class="w"> </span><span class="p">[</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">nBodyStep</span><span class="p">(</span><span class="nx">coords</span><span class="p">,</span><span class="w"> </span><span class="nx">masses</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaT</span><span class="p">,</span><span class="w"> </span><span class="mf">10</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">1.5e11</span><span class="p">,</span><span class="w"> </span><span class="nx">nBodies</span><span class="p">,</span><span class="w"> </span><span class="nx">G</span><span class="p">);</span><span class="w"> </span><span class="c1">// Update</span><span class="w"></span> +<span class="w"> </span><span class="nx">coordsRecord</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">deepCopyCoordsArray</span><span class="p">(</span><span class="nx">coords</span><span class="p">));</span><span class="w"></span> +<span class="w"> </span><span class="nx">massRecord</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">masses</span><span class="p">.</span><span class="nx">slice</span><span class="p">());</span><span class="w"> </span><span class="c1">// Add to records</span><span class="w"></span> +<span class="w"> </span><span class="nx">tInd</span><span class="o">++</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">time</span><span class="p">[</span><span class="nx">tInd</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="c1">//console.log(`currently at t = ${(t / yearSec).toFixed(2)} years\r`);</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="sb">`final time = </span><span class="si">${</span><span class="nx">time</span><span class="p">[</span><span class="nx">tInd</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">yearSec</span><span class="si">}</span><span class="sb"> years with </span><span class="si">${</span><span class="nx">nBodies</span><span class="si">}</span><span class="sb"> bodies remaining`</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="c1">// Set button text to Start Simulation</span><span class="w"></span> +<span class="w"> </span><span class="nx">btn</span><span class="p">.</span><span class="nx">innerHTML</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">prevText</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">coordsRecord</span><span class="p">,</span><span class="w"> </span><span class="nx">massRecord</span><span class="p">,</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">tInd</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">1</span><span class="p">)];</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + + +<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="p">[</span><span class="nx">coordsRecordR</span><span class="p">,</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">tR</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">genNBodyResults</span><span class="p">(</span><span class="mf">256</span><span class="p">,</span><span class="mf">1</span><span class="p">,</span><span class="mf">1001</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="c1">//console.log(coordsRecordR);</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">yearSec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">365</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">3600</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">createFrame</span><span class="p">(</span><span class="nx">coordsR</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">coordsR</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="o">!</span><span class="nx">coordsR</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="o">!</span><span class="nx">coordsR</span><span class="p">[</span><span class="mf">1</span><span class="p">])</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">[];</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> + +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">traceCentralStar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="nx">coordsR</span><span class="p">[</span><span class="mf">0</span><span class="p">][</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">1.5e11</span><span class="p">],</span><span class="w"></span> +<span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="nx">coordsR</span><span class="p">[</span><span class="mf">1</span><span class="p">][</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">1.5e11</span><span class="p">],</span><span class="w"></span> +<span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s1">'markers'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">type</span><span class="o">:</span><span class="w"> </span><span class="s1">'scatter'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s1">'Central star'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">marker</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">color</span><span class="o">:</span><span class="w"> </span><span class="s1">'gold'</span><span class="p">,</span><span class="w"> </span><span class="nx">symbol</span><span class="o">:</span><span class="w"> </span><span class="s1">'star'</span><span class="p">,</span><span class="w"> </span><span class="nx">size</span><span class="o">:</span><span class="w"> </span><span class="mf">10</span><span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="p">};</span><span class="w"></span> + +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">xCoords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coordsR</span><span class="p">[</span><span class="mf">0</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="mf">1</span><span class="p">).</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">1.5e11</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">yCoords</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">coordsR</span><span class="p">[</span><span class="mf">1</span><span class="p">].</span><span class="nx">slice</span><span class="p">(</span><span class="mf">1</span><span class="p">).</span><span class="nx">map</span><span class="p">(</span><span class="nx">y</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">1.5e11</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">traceOtherBodies</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="nx">xCoords</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="nx">yCoords</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s1">'markers'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">type</span><span class="o">:</span><span class="w"> </span><span class="s1">'scatter'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s1">''</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">marker</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">color</span><span class="o">:</span><span class="w"> </span><span class="s1">'dodgerblue'</span><span class="p">,</span><span class="w"> </span><span class="nx">symbol</span><span class="o">:</span><span class="w"> </span><span class="s1">'circle'</span><span class="p">,</span><span class="w"> </span><span class="nx">size</span><span class="o">:</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="p">};</span><span class="w"></span> + +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">traceCentralStar</span><span class="p">,</span><span class="w"> </span><span class="nx">traceOtherBodies</span><span class="p">];</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> + + +<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">createLayout</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">text</span><span class="o">:</span><span class="w"> </span><span class="sb">`N-Body Problem: t = </span><span class="si">${</span><span class="nb">Number</span><span class="p">(</span><span class="nx">t</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">yearSec</span><span class="p">).</span><span class="nx">toFixed</span><span class="p">(</span><span class="mf">3</span><span class="p">)</span><span class="si">}</span><span class="sb"> years`</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="mf">0.03</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="mf">0.97</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">xanchor</span><span class="o">:</span><span class="w"> </span><span class="s1">'left'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">yanchor</span><span class="o">:</span><span class="w"> </span><span class="s1">'top'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">font</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">size</span><span class="o">:</span><span class="w"> </span><span class="mf">14</span><span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="nx">xaxis</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s1">'x [AU]'</span><span class="p">,</span><span class="w"> </span><span class="nx">range</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mf">2.1</span><span class="p">,</span><span class="w"> </span><span class="mf">2.1</span><span class="p">]</span><span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="nx">yaxis</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="s1">'y [AU]'</span><span class="p">,</span><span class="w"> </span><span class="nx">range</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mf">2.1</span><span class="p">,</span><span class="w"> </span><span class="mf">2.1</span><span class="p">],</span><span class="w"> </span><span class="nx">scaleanchor</span><span class="o">:</span><span class="w"> </span><span class="s1">'x'</span><span class="p">,</span><span class="w"> </span><span class="nx">scaleratio</span><span class="o">:</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="nx">showlegend</span><span class="o">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">margin</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">l</span><span class="o">:</span><span class="w"> </span><span class="mf">60</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="o">:</span><span class="w"> </span><span class="mf">40</span><span class="p">,</span><span class="w"> </span><span class="nx">t</span><span class="o">:</span><span class="w"> </span><span class="mf">40</span><span class="p">,</span><span class="w"> </span><span class="nx">b</span><span class="o">:</span><span class="w"> </span><span class="mf">40</span><span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="mf">800</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">height</span><span class="o">:</span><span class="w"> </span><span class="mf">800</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">plot_bgcolor</span><span class="o">:</span><span class="w"> </span><span class="s1">'black'</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="p">};</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">animateNBodyProblem</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">nFrames</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">tR</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">nFrames</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">frameData</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createFrame</span><span class="p">(</span><span class="nx">coordsRecordR</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span><span class="w"></span> +<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">layout</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createLayout</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="c1">//Plotly.newPlot(plotDiv, frameData, layout);</span><span class="w"></span> +<span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">Plotly</span><span class="p">.</span><span class="nx">animate</span><span class="p">(</span><span class="s2">"plot"</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">data</span><span class="o">:</span><span class="w"> </span><span class="nx">frameData</span><span class="p">,</span><span class="w"> </span><span class="nx">layout</span><span class="o">:</span><span class="w"> </span><span class="nx">layout</span><span class="w"></span> +<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">staticPlot</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">transition</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">duration</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="p">},</span><span class="w"></span> +<span class="w"> </span><span class="nx">frame</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">duration</span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nx">redraw</span><span class="o">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="p">});</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<span class="w"> </span><span class="nx">Plotly</span><span class="p">.</span><span class="nx">newPlot</span><span class="p">(</span><span class="s1">'plot'</span><span class="p">,</span><span class="w"> </span><span class="nx">frameData</span><span class="p">,</span><span class="w"> </span><span class="nx">layout</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="w"> </span><span class="p">}</span><span class="w"></span> +<span class="p">}</span><span class="w"></span> + +<span class="nx">animateNBodyProblem</span><span class="p">();</span><span class="w"></span> +</code></pre> +</div> + +<h2>Playground</h2> + +<script src="https://cdn.plot.ly/plotly-latest.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/11.8.0/math.js"></script> +<script src="/assets/n-body/script.js"></script> +<div id="main-plot-div"> +<div id="plot"></div> + +<label for="speedControl">Speed for 3-Body Visualisation</label> +<input type="range" min="1" max="20" value="10" id="speedControl"> +<label for="nBodies">Number of Bodies for n-Body Simulation (5-500)</label> +<input type="range" min="5" max="500" value="256" id="nBodies"> +</div> +<button type="button" id="startSim1" onclick="plotEarthSun()">Sun-Earth Orbit</button> +<button type="button" id="startSim2" onclick="plotClassic3BodyProblem()">Classic 3-Body Problem</button> +<button type="button" id="startSim3" onclick="plotRandom3BodySimulation()">Random n-Body Simulation</button> +<script> +function clearAl() { + plotOrbit = false; + plotClassic = false; + plotRandom = false; +} + +function plotEarthSun() { + clearAl(); + plotOrbit = true; + calculateAndPlot(); + setTimeout(function(){ + calculateAndPlot() + }, 500); + } + +function plotClassic3BodyProblem() { + clearAl(); + plotClassic = true; + calculateAndPlot(); + setTimeout(function(){ + calculateAndPlot() + }, 500); + } + +function plotRandom3BodySimulation() { + clearAl(); + plotRandom = true; + calculateAndPlot(); + } + + +</script> + +<script> + document.getElementById("speedControl").addEventListener("input", (event) => { + const speedPercentage = parseInt(event.target.value, 10); + delay = speedPercentage; // Adjust the delay based on the trackbar value +}); + document.getElementById("nBodies").addEventListener("input", (event) => { + nBodies = parseInt(event.target.value, 10); + }); + + </script> + <noscript> This post requires JavaScript to be viewed properly :( </noscript> |