Skip to main content

list manipulation - Solving and Animating Three Body Problem


I am attempting to solve a three-body problem using the Lagrange formalism, with a 1/r potential.


I started off by defining T and U (kinetic and potential energy) as follows:


Tx = .5 m1  x1'[t]^2 + .5 m2 x2'[t]^2 + .5 m3  x3'[t]^2;
Ty = .5 m1 y1'[t]^2 + .5 m2 y2'[t]^2 + .5 m3 y3'[t]^2;

U1 = G m1 m2 /((x1[t] - x2[t])^2 + (y1[t] - y2[t])^2)^.5 +
G m1 m3 /((x1[t] - x3[t])^2 + (y1[t] - y3[t])^2)^.5;

U2 = G m2 m1 /((x2[t] - x1[t])^2 + (y2[t] - y1[t])^2)^.5 +

G m2 m3 /((x2[t] - x3[t])^2 + (y2[t] - y3[t])^2)^.5;

U3 = G m3 m1 /((x3[t] - x1[t])^2 + (y3[t] - y1[t])^2)^.5 +
G m3 m2 /((x3[t] - x2[t])^2 + (y3[t] - y2[t])^2)^.5;
U = U1 + U2 + U3;
T = Tx + Ty;
lag = T - U;

And assigning arbitrary values to constants.


Where x1[t] and y1[t] are the x and y coordinates of mass 1, and the same for masses 2 and 3.



From here, I found the Euler-Lagrange EQs via the function


EL[q_] := D[lag, q] - Dt[D[lag, D[q, t]], t];

Where I input x1[t], x2[t], etc. as q. I stored them in a list such that


eqnx[1] = EL[x1[t]] == 0 // FullSimplify;
eqny[1] = EL[y1[t]] == 0 // FullSimplify;

And changed indices for the other functions (ie the E-L equation for x2 was stored in eqnx[2], etc). I combined all these elements, along with ICs, into a master list.


IC1 = {x1[0] == 0, y1[0] == 0, x1'[0] == 0, y1'[0] == 0};
IC2 = {x2[0] == 10, y2[0] == 0, x2'[0] == 0, y2'[0] == 0};

IC3 = {x3[0] == 0, y3[0] == 15, x3'[0] == 0, y3'[0] == 0};
eqnlist = Join[delist, IC1, IC2, IC3];

Where delist was created by joining all the elements of eqnx and eqny.


I then plugged eqnlist into NDSolve with arbitrary bounds of t (since DSolve could/would not solve a complicated, non-linear system of ODEs for me) as follows:


soln = NDSolve[eqnlist, {x1, y1, x2, y2, x3, y3}, {t, 0, 20}][[1]];

From here, I am stuck. soln is a list with six elements, each corresponding to one of the functions I want, but I am unable to store them into x1[t], y1[t], etc; when I run


x1[t]/.soln[[1]];
Plot[x1[t], {t,0,20}]


I get a blank screen for x1 and every other function. Rather annoying! This makes it impossible for me to even animate it; I created points as follows:


point1 = Graphics[{PointSize[Medium], Red, 
Point[Dynamic[{x1[t], y1[t]}]]}];

With the indices and colors changed for masses 2 and 3, and have set up Animate as follows:


Animate[Show[point1, point2, point3], {t, 0, 20}]

I am not sure how to resolve my assigning-functions-properly problem, and I am reasonably sure that this may solve my animation problem (or it could be that my animation is bugged to begin with!).



Answer




Generally always check Demonstrations site for good code. I cannot not mention an excellent "classic" of planar three body problem by Stephen Wolfram and Michael Trott. Code is short and I verified it runs in the latest M10.1. I slightly changed variable labels so code parses better here, removed MaxRecursion -> ControlActive[3, 9] from plot option and added some new style.


enter image description here


threeBodyTrajectories[{{x10_, y10_}, {x20_, y20_}, {x30_, y30_}},
{{vx10_, vy10_}, {vx20_, vy20_}, {vx30_, vy30_}}, {m1_, m2_, m3_},
T_, plotType : ("x" | "v"),
plotOptions___] :=
Module[{nds, Tmax, prolog, funsToPlot},
nds = NDSolve[
{x1'[t] == vx1[t], y1'[t] == vy1[t],
x2'[t] == vx2[t], y2'[t] == vy2[t],

x3'[t] == vx3[t], y3'[t] == vy3[t],
m1 vx1'[t] == -((
m1 m2 (x1[t] -
x2[t]))/((x1[t] - x2[t])^2 + (y1[t] - y2[t])^2)^(3/2)) - (
m1 m3 (x1[t] -
x3[t]))/((x1[t] - x3[t])^2 + (y1[t] - y3[t])^2)^(3/2),
m1 vy1'[t] == -((
m1 m2 (y1[t] -
y2[t]))/((x1[t] - x2[t])^2 + (y1[t] - y2[t])^2)^(3/2)) - (
m1 m3 (y1[t] -

y3[t]))/((x1[t] - x3[t])^2 + (y1[t] - y3[t])^2)^(3/2),
m2 vx2'[t] == (
m1 m2 (x1[t] -
x2[t]))/((x1[t] - x2[t])^2 + (y1[t] - y2[t])^2)^(3/2) - (
m2 m3 (x2[t] -
x3[t]))/((x2[t] - x3[t])^2 + (y2[t] - y3[t])^2)^(3/2),
m2 vy2'[t] == (
m1 m2 (y1[t] -
y2[t]))/((x1[t] - x2[t])^2 + (y1[t] - y2[t])^2)^(3/2) - (
m2 m3 (y2[t] -

y3[t]))/((x2[t] - x3[t])^2 + (y2[t] - y3[t])^2)^(3/2),
m3 vx3'[t] == (
m1 m3 (x1[t] -
x3[t]))/((x1[t] - x3[t])^2 + (y1[t] - y3[t])^2)^(3/2) + (
m2 m3 (x2[t] -
x3[t]))/((x2[t] - x3[t])^2 + (y2[t] - y3[t])^2)^(3/2),
m3 vy3'[t] == (
m1 m3 (y1[t] -
y3[t]))/((x1[t] - x3[t])^2 + (y1[t] - y3[t])^2)^(3/2) + (
m2 m3 (y2[t] -

y3[t]))/((x2[t] - x3[t])^2 + (y2[t] - y3[t])^2)^(3/2),
x1[0] == x10, y1[0] == y10, x2[0] == x20, y2[0] == y20,
x3[0] == x30, y3[0] == y30,
vx1[0] == vx10, vy1[0] == vy10, vx2[0] == vx20, vy2[0] == vy20,
vx3[0] == vx30, vy3[0] == vy30},
{x1, x2, x3, y1, y2, y3, vx1, vx2, vx3, vy1, vy2, vy3}, {t, 0,
T}];
If[Head[nds] =!= NDSolve,
Tmax = nds[[1, 1, 2, 1, 1, 2]];
funsToPlot =

If[plotType ===
"x", {{x1[t], y1[t]}, {x2[t], y2[t]}, {x3[t], y3[t]}},
{{vx1[t], vy1[t]}, {vx2[t], vy2[t]}, {vx3[t], vy3[t]}}] /.
nds[[1]];
prolog = {PointSize[0.01],
Transpose[{{RGBColor[1, .2, 0], RGBColor[.5, .8, 0],
RGBColor[.2, .6, 1]}, Point /@ (funsToPlot /. t -> 0)}]};
ParametricPlot[Evaluate[funsToPlot], {t, 0, Tmax},
PlotStyle -> {RGBColor[1, .2, 0], RGBColor[.5, .8, 0],
RGBColor[.2, .6, 1]}, Frame -> False, PlotRange -> All,

AspectRatio -> 1,
Prolog -> prolog, Frame -> True, Axes -> False,
FrameTicks -> False, PlotTheme -> "Web", plotOptions],
Text["Degenerate initial conditions."]]
] // Quiet

Manipulate[
threeBodyTrajectories[{xy10, xy20, xy30},
{vxy10, vxy20, vxy30}, {10^m1Exp, 10^m2Exp, 10^m3Exp}, T, xv,
ImageSize -> {350, 350}] ,

{{xv, "x", "position/velocity"}, {"x" -> "position",
"v" -> "velocity"}},
{{T, 3, "time"}, 0.001, 10},
{{xy10, { 0.97000436, -0.24308753}, "Xi1"}, {-2, -2}, {2, 2},
ImageSize -> Small},
{{xy20, {-0.97000436, 0.24308753}, "Xi2"}, {-2, -2}, {2, 2},
ImageSize -> Small},
{{xy30, {0, 0}, "Xi3"}, {-2, -2}, {2, 2}, ImageSize -> Small},
{{vxy10, {0.93240737/2, 0.86473146/2}, "Vi1"}, {-2, -2}, {2, 2},
ImageSize -> Small},

{{vxy20, {0.93240737/2, 0.86473146/2}, "Vi2"}, {-2, -2}, {2, 2},
ImageSize -> Small},
{{vxy30, {-0.93240737, -0.86473146}, "Vi3"}, {-2, -2}, {2, 2},
ImageSize -> Small},
{{m1Exp, 0, "M1"}, -3, 3}, {{m2Exp, 0, "M2"}, -3,
3}, {{m3Exp, 0, "M3"}, -3, 3},
ControlPlacement -> {Top, Top, Left, Left, Left, Right, Right, Right,
Bottom, Bottom, Bottom}, SaveDefinitions -> True,
AutorunSequencing -> {3, 5, 7}]


Another very good coder, Enrique Zeleny, did an awesome version for Recently Discovered Periodic Solutions of the Three-Body Problem - recommend to check out the code, it is free dowload-able at the linked webpage.


enter image description here


The demo is based on a recent article


Three Classes of Newtonian Three-Body Planar Periodic Orbits


that made a lot of noise even in popular media. Another cool thing in the paper is that the authors suggested an excellent coordinate system where it is easy to comprehend 3-body motion (perhaps useful to your animation).


enter image description here


and that coordinate system got implementation in the Enrique demo too:


enter image description here


Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...

list manipulation - Selecting multiple columns from a matrix?

Sample data: data = { {{2013, 1, 1}, 24.13, 167.67, 231.82}, {{2013, 1, 2}, 32.15, 170.92, 225.99}, {{2013, 1, 3}, 35.43, 172.68, 221.67}, {{2013, 1, 4}, 36.73, 173.05, 218.32}, {{2013, 1, 5}, 58.19, 165.96, 197.05}, {{2013, 1, 6}, 69.99, 163.50, 187.52}, {{2013, 1, 7}, 71.37, 154.21, 175.58}, {{2013, 1, 8}, 72.51, 149.66, 163.25}}; I want a DateListPlot with three graphs, so for a matrix formed by columns 1 and 2, one for columns 1 and 3, and 1 for columns 1 and 4. At the moment I'm using this code: data2 = Transpose[{data[[All, 1]], data[[All, 2]]}]; data3 = Transpose[{data[[All, 1]], data[[All, 3]]}]; data4 = Transpose[{data[[All, 1]], data[[All, 4]]}]; DateListPlot[{data2, data3, data4}, Joined -> True, Filling -> {3 -> {1}}] but I have a hunch that this can be done more efficiently. I don't like the Transpose s in particular. Any ideas? edit (for extra credit) What if I need to multiply the second column by 2, which in my solution is simp...