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

equation solving - Invert and fit implicitly defined curve

I need to fit an implicitly defined curve. I thought I could get some data out of Solve , and then using FindFit . Therefore, I would like to find the relation the parametric curve defined by $F(x,y)=0$: Solve[-(1/2) + 1/2 (0.41202 BesselK[0, 0.1 Sqrt[x^2 + y^2]] + (0.101483 x BesselK[1, 0.1 Sqrt[x^2 + y^2]])/Sqrt[x^2 + y^2]) == 0, y] But I can't get an output: Solve was unable to solve the system with inexact coefficients or the system obtained by direct rationalization of inexact numbers present in the system. Since many of the methods used by Solve require exact input, providing Solve with an exact version of the system may help. >> Edit: In particular, I would like to fit the data coming from the curve with the expression of another curve, and not with a function $f(x)$. In particular, since this clearly looks like a cardioid , I would like it to fit to something like it. What other strategies could I try?

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...