From 3d902334815db764d0cb6e4bbf6c553ff1fd6f2e Mon Sep 17 00:00:00 2001 From: navanchauhan Date: Mon, 1 May 2023 13:03:49 -0600 Subject: re-add 3body sim --- Content/posts/2023-04-30-n-body-simulation.md | 33 +++++--- Resources/assets/n-body/script.js | 112 +++++++++++++++++++++++++- docs/assets/n-body/script.js | 112 +++++++++++++++++++++++++- docs/feed.rss | 42 +++++++--- docs/posts/2023-04-30-n-body-simulation.html | 38 ++++++--- 5 files changed, 296 insertions(+), 41 deletions(-) diff --git a/Content/posts/2023-04-30-n-body-simulation.md b/Content/posts/2023-04-30-n-body-simulation.md index 52f38da..e3d6a9d 100644 --- a/Content/posts/2023-04-30-n-body-simulation.md +++ b/Content/posts/2023-04-30-n-body-simulation.md @@ -13,12 +13,9 @@ Adapted from the Numerics Tutorial - [kirklong/ThreeBodyBot](https://github.com/ Workflow: * Understand the problem - * Visualise a basic orbit - * Solve and plot the classic figure-8 orbit - -* random n-body solution generator +* 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.** @@ -28,7 +25,7 @@ The n-body problem is a classic puzzle in physics (and thus astrophysics) and ma 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. +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.[1] 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. @@ -175,7 +172,7 @@ Now that we have the data for the Sun's position, Earth's orbit, and the referen ## 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. +The figure of 8 solution[2] 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. @@ -643,6 +640,10 @@ animateNBodyProblem();
+ +
@@ -652,12 +653,14 @@ animateNBodyProblem();
- + + @@ -698,7 +708,8 @@ function plotRandom3BodySimulation() { - +## References + +1. Barrow-Green, June (2008), "The Three-Body Problem", in Gowers, Timothy; Barrow-Green, June; Leader, Imre (eds.), *The Princeton Companion to Mathematics*, Princeton University Press, pp. 726–728 +2. Moore, Cristopher (1993), "Braids in classical dynamics", *Physical Review Letters*, 70 (24): 3675–3679 \ No newline at end of file diff --git a/Resources/assets/n-body/script.js b/Resources/assets/n-body/script.js index e87d92c..6042e27 100644 --- a/Resources/assets/n-body/script.js +++ b/Resources/assets/n-body/script.js @@ -2,6 +2,7 @@ var plotOrbit = true var plotClassic = false var plotRandom = false +var plotRandom3Body = false var plotIndex = 0 var delay = 10 var tailLength = 1; @@ -288,6 +289,36 @@ function initCondGen(nBodies, vRange = [-7e3, 7e3], posRange = [-35, 35]) { return {m: m.map(x => x * 2e30), rad: rad.map(x => x * 7e8), coords: coords}; } +function random3BodySimSolver(tStop, nTPts, nBodiesStop=2, G=6.674e-11) { + let initConditions = initCondGen(3,[-7e3, 7e3],[-5, 5]); + let myMasses = initConditions.m; + let myCoords = initConditions.coords; + + let nBodies3B = 3; + + 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(myCoords)]; + const massRecord = [myMasses.slice()]; // Initialize records with initial conditions + + while (tInd < nTPts && nBodies3B > nBodiesStop) { + [myCoords, myMasses, nBodies3B] = nBodyStep(myCoords, myMasses, deltaT, 10 * 1.5e11, nBodies3B, G); // Update + coordsRecord.push(deepCopyCoordsArray(myCoords)); + massRecord.push(myMasses.slice()); // Add to records + tInd++; + t = time[tInd]; + } + + console.log(nBodies3B) + + return [coordsRecord, massRecord, time.slice(0, tInd + 1)]; + +} + function calculateAndPlot() { try { @@ -413,8 +444,8 @@ function calculateAndPlot() { 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, + //width: 800, + //height: 800, plot_bgcolor: 'black', }; } @@ -448,6 +479,79 @@ function calculateAndPlot() { animateNBodyProblem(); + } else if (plotRandom3Body==true) { + let [coordsRecord3, _, t3] = random3BodySimSolver(1,1000); + + const yearSec = 365 * 24 * 3600; + + function createFrame(coords3) { + if (!coords3 || !coords3[0] || !coords3[1]) { + return []; + } + + const xCoords = coords3[0].slice(0).map(x => x / 1.5e11); + const yCoords = coords3[1].slice(0).map(y => y / 1.5e11); + + const traceOtherBodies = { + x: xCoords, + y: yCoords, + mode: 'markers', + type: 'scatter', + name: '', + marker: { color: 'dodgerblue', symbol: 'circle', size: 5 }, + }; + + return [traceOtherBodies]; + } + + function createLayout(i) { + return { + title: { + text: `3-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]' }, + yaxis: { title: 'y [AU]', scaleanchor: 'x', scaleratio: 1 }, + showlegend: false, + margin: { l: 60, r: 40, t: 40, b: 40 }, + //width: 800, + //height: 800, + plot_bgcolor: 'black', + }; + } + + function animate3BodyProblem() { + const nFrames = t3.length; + + for (let i = 0; i < nFrames; i++) { + const frameData = createFrame(coordsRecord3[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); + } + } + } + + animate3BodyProblem(); + } else if (plotClassic==true) { // Initial conditions setup let M = [1, 1, 1]; @@ -478,11 +582,12 @@ animateNBodyProblem(); 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) { + } if (plotIndex > time.length) { plotIndex = 0; } else { tailLength = plotIndex - tailLength; @@ -493,6 +598,7 @@ animateNBodyProblem(); try { time[currentIndex].toFixed(3); } catch (e) { + console.log(e) currentIndex = 0; } diff --git a/docs/assets/n-body/script.js b/docs/assets/n-body/script.js index e87d92c..6042e27 100644 --- a/docs/assets/n-body/script.js +++ b/docs/assets/n-body/script.js @@ -2,6 +2,7 @@ var plotOrbit = true var plotClassic = false var plotRandom = false +var plotRandom3Body = false var plotIndex = 0 var delay = 10 var tailLength = 1; @@ -288,6 +289,36 @@ function initCondGen(nBodies, vRange = [-7e3, 7e3], posRange = [-35, 35]) { return {m: m.map(x => x * 2e30), rad: rad.map(x => x * 7e8), coords: coords}; } +function random3BodySimSolver(tStop, nTPts, nBodiesStop=2, G=6.674e-11) { + let initConditions = initCondGen(3,[-7e3, 7e3],[-5, 5]); + let myMasses = initConditions.m; + let myCoords = initConditions.coords; + + let nBodies3B = 3; + + 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(myCoords)]; + const massRecord = [myMasses.slice()]; // Initialize records with initial conditions + + while (tInd < nTPts && nBodies3B > nBodiesStop) { + [myCoords, myMasses, nBodies3B] = nBodyStep(myCoords, myMasses, deltaT, 10 * 1.5e11, nBodies3B, G); // Update + coordsRecord.push(deepCopyCoordsArray(myCoords)); + massRecord.push(myMasses.slice()); // Add to records + tInd++; + t = time[tInd]; + } + + console.log(nBodies3B) + + return [coordsRecord, massRecord, time.slice(0, tInd + 1)]; + +} + function calculateAndPlot() { try { @@ -413,8 +444,8 @@ function calculateAndPlot() { 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, + //width: 800, + //height: 800, plot_bgcolor: 'black', }; } @@ -448,6 +479,79 @@ function calculateAndPlot() { animateNBodyProblem(); + } else if (plotRandom3Body==true) { + let [coordsRecord3, _, t3] = random3BodySimSolver(1,1000); + + const yearSec = 365 * 24 * 3600; + + function createFrame(coords3) { + if (!coords3 || !coords3[0] || !coords3[1]) { + return []; + } + + const xCoords = coords3[0].slice(0).map(x => x / 1.5e11); + const yCoords = coords3[1].slice(0).map(y => y / 1.5e11); + + const traceOtherBodies = { + x: xCoords, + y: yCoords, + mode: 'markers', + type: 'scatter', + name: '', + marker: { color: 'dodgerblue', symbol: 'circle', size: 5 }, + }; + + return [traceOtherBodies]; + } + + function createLayout(i) { + return { + title: { + text: `3-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]' }, + yaxis: { title: 'y [AU]', scaleanchor: 'x', scaleratio: 1 }, + showlegend: false, + margin: { l: 60, r: 40, t: 40, b: 40 }, + //width: 800, + //height: 800, + plot_bgcolor: 'black', + }; + } + + function animate3BodyProblem() { + const nFrames = t3.length; + + for (let i = 0; i < nFrames; i++) { + const frameData = createFrame(coordsRecord3[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); + } + } + } + + animate3BodyProblem(); + } else if (plotClassic==true) { // Initial conditions setup let M = [1, 1, 1]; @@ -478,11 +582,12 @@ animateNBodyProblem(); 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) { + } if (plotIndex > time.length) { plotIndex = 0; } else { tailLength = plotIndex - tailLength; @@ -493,6 +598,7 @@ animateNBodyProblem(); try { time[currentIndex].toFixed(3); } catch (e) { + console.log(e) currentIndex = 0; } diff --git a/docs/feed.rss b/docs/feed.rss index 760ae20..23f6a2f 100644 --- a/docs/feed.rss +++ b/docs/feed.rss @@ -4,8 +4,8 @@ Navan's Archive Rare Tips, Tricks and Posts https://web.navan.dev/en - Mon, 01 May 2023 00:26:41 -0000 - Mon, 01 May 2023 00:26:41 -0000 + Mon, 01 May 2023 12:58:21 -0000 + Mon, 01 May 2023 12:58:21 -0000 250 @@ -4147,10 +4147,10 @@ Seeing that you are reading this on Mastodon, and that I have updated this secti

Workflow:

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.

@@ -4161,7 +4161,7 @@ Seeing that you are reading this on Mastodon, and that I have updated this secti

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.

+

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.[1] 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.

@@ -4307,7 +4307,7 @@ Next, the function dR takes the position r and velocity v of Earth as input and

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.

+

The figure of 8 solution[2] 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.

@@ -4773,6 +4773,10 @@ Next, the function dR takes the position r and velocity v of Earth as input and
+ +
@@ -4782,12 +4786,14 @@ Next, the function dR takes the position r and velocity v of Earth as input and
- + + @@ -4828,9 +4841,12 @@ function plotRandom3BodySimulation() { - +

References

+ +
    +
  1. Barrow-Green, June (2008), "The Three-Body Problem", in Gowers, Timothy; Barrow-Green, June; Leader, Imre (eds.), The Princeton Companion to Mathematics, Princeton University Press, pp. 726–728
  2. +
  3. Moore, Cristopher (1993), "Braids in classical dynamics", Physical Review Letters, 70 (24): 3675–3679
  4. +
]]> diff --git a/docs/posts/2023-04-30-n-body-simulation.html b/docs/posts/2023-04-30-n-body-simulation.html index 302e2e0..7d8a710 100644 --- a/docs/posts/2023-04-30-n-body-simulation.html +++ b/docs/posts/2023-04-30-n-body-simulation.html @@ -63,10 +63,10 @@

Workflow:

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.

@@ -77,7 +77,7 @@

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.

+

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.[1] 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.

@@ -223,7 +223,7 @@ Next, the function dR takes the position r and velocity v of Earth as input and

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.

+

The figure of 8 solution[2] 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.

@@ -689,6 +689,10 @@ Next, the function dR takes the position r and velocity v of Earth as input and
+ +
@@ -698,12 +702,14 @@ Next, the function dR takes the position r and velocity v of Earth as input and
- + + @@ -744,9 +757,12 @@ function plotRandom3BodySimulation() { - +

References

+ +
    +
  1. Barrow-Green, June (2008), "The Three-Body Problem", in Gowers, Timothy; Barrow-Green, June; Leader, Imre (eds.), The Princeton Companion to Mathematics, Princeton University Press, pp. 726–728
  2. +
  3. Moore, Cristopher (1993), "Braids in classical dynamics", Physical Review Letters, 70 (24): 3675–3679
  4. +
If you have scrolled this far, consider subscribing to my mailing list here. You can subscribe to either a specific type of post you are interested in, or subscribe to everything with the "Everything" list.