-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy paththreebodyproblem.cpp
More file actions
134 lines (107 loc) · 5.65 KB
/
Copy paththreebodyproblem.cpp
File metadata and controls
134 lines (107 loc) · 5.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <iostream>
#include <cmath>
#include <cpgplot.h>
#include <unistd.h>
const double G = 1.0; // normalized gravity constant (this is only here so I could change it for testing, however, if it stays at 1.0 it could be removed from the program)
struct Body {
double mass; // mass of the object
double x, y; // coordinates for x and y
double vx, vy; // velocity for x and y
double ax, ay; // acceleration for x and y
};
// function to compute the gravitational force between two bodies
void compute(const Body& body1, const Body& body2, double& fx, double& fy) {
double dx = body2.x - body1.x; // delta x (distance between the two bodies in x direction)
double dy = body2.y - body1.y; // delta y (distance between the two bodies in y direction)
double r = sqrt(dx * dx + dy * dy); // distance between the two bodies using pythagorean theorem
double r_cubed = r * r * r; // r^3
// gravitational force components
fx = G * body1.mass * body2.mass * dx / r_cubed; // force in the x direction
fy = G * body1.mass * body2.mass * dy / r_cubed; // force in the y direction
}
// function to update body positions and velocities using the leapfrog method
void iter(Body& body, const Body& other1, const Body& other2, double dt) {
double fx1, fy1, fx2, fy2; // forces fx1 and fy1 for other1, fx2 and fy2 for other2 against body
// compute forces between the bodies
compute(body, other1, fx1, fy1); // compute force for x and y directions against other1
compute(body, other2, fx2, fy2); // compute force for x and y directions against other2
// update acceleration
body.ax = (fx1 + fx2) / body.mass; // acceleration in x direction
body.ay = (fy1 + fy2) / body.mass; // acceleration in y direction
// leapfrog method: update velocity at half step
body.vx += 0.5 * body.ax * dt; // velocity in x direction
body.vy += 0.5 * body.ay * dt; // velocity in y direction
// update position
body.x += body.vx * dt; // position in x direction
body.y += body.vy * dt; // position in y direction
// compute forces again with updated positions
compute(body, other1, fx1, fy1); // compute against other1
compute(body, other2, fx2, fy2); // compute against other2
// update acceleration again
body.ax = (fx1 + fx2) / body.mass; // acceleration in x direction
body.ay = (fy1 + fy2) / body.mass; // acceleration in y direction
// leapfrog method: update velocity at full step
body.vx += 0.5 * body.ax * dt; // velocity in x direction
body.vy += 0.5 * body.ay * dt; // velocity in y direction
}
int main() {
float size = 1.5; // size of the plot (default 1.5 for bumblebee example)
double s = 0.7; // scale factor for use with circle test
// all possible test cases used in the report
// circle test
// Body body1 = {1.0, 1.0, 0.0, 0.0, s * 1.0};
// Body body2 = {1.0, -0.5, sqrt(3)/2, s * -sqrt(3)/2, s * -0.5};
// Body body3 = {1.0, -0.5, -sqrt(3)/2, s * sqrt(3)/2, s * -0.5};
// first chaos test
// Body body1 = {1.0, 0.5, 0.0, 1.0, 1.0}; // random orbit that was changed to 1.01 mass for chaos test
// Body body2 = {1.0, 1.0, 0.1, -0.3, -0.2};
// Body body3 = {1.0, -0.5, -1.0, -0.5, 0.5};
// Body body1 = {1.0, 0.5, 0.0, 1.0, 0.2}; // small object orbiting a smaller object affecting a third object
// Body body2 = {1.5, 0.3, 0.1, -0.5, -0.5};
// Body body3 = {0.5, -0.2, -1.3, -0.4, 0.5};
// second chaos test
// Body body1 = {1.0, 0.5, 0.0, 0.7, 0.4}; // changed the position of this object from y = 0.0 to y = 0.1
// Body body2 = {1.0, -0.5, 0.1, 0.4, -0.6};
// Body body3 = {1.0, 0.5, -0.9, 0.8, -0.6};
// large mass test
// Body body1 = {100.0, 0.0, 0.0, 0.0, 0.0}; // 0 velocity large mass in the middle
// Body body2 = {1.0, -2.0, 0.0, 0.0, 5.0};
// Body body3 = {1.0, 2.0, 0.0, 0.0, -5.0};
// cases from https://arxiv.org/abs/1303.0181v1
// double vsx = 0.51394; // II.C.2a yin-yang I
// double vsy = 0.30474;
// double vsx = 0.08330; // I.B.5 goggles
// double vsy = 0.12789;
double vsx = 0.18428; // I.A.3 bumblebee (high period)
double vsy = 0.58719;
// for use with above
Body body1 = {1.0, -1.0, 0.0, vsx, vsy};
Body body2 = {1.0, 1.0, 0.0, vsx, vsy};
Body body3 = {1.0, 0.0, 0.0, -2.0 * vsx, -2.0 * vsy};
// random test case for fast moving objects
// Body body1 = {1.0, -1.0, -1.0, 0.01, 0.01};
// Body body2 = {0.01, 0.5, 0.5, 1.0, -1.0};
// Body body3 = {0.0001, 0.45, 0.45, 3.0, 0.0};
double dt = 0.0001; // time step
double totaltime = 100.0; // total time
int steps = static_cast<int>(totaltime / dt); // number of steps (total time divided by time step)
cpgbeg(0, "/XWINDOW", 1, 1); // begin a new plot
cpgenv(-size, size, -size, size, 0, 0); // set it to the size of the plot given
cpgask(0);
cpglab("x", "y", "Three Body Problem"); // label the plot
for (int step = 0; step < steps; ++step) { // iterate through the steps
iter(body1, body2, body3, dt); // body1 against body2 and body3
iter(body2, body1, body3, dt); // body2 against body1 and body3
iter(body3, body1, body2, dt); // body3 against body1 and body2
cpgsci(5); // set line to colour blue
cpgpt1(body1.x, body1.y, 1); // plot body1 in blue
cpgsci(2); // set line to colour red
cpgpt1(body2.x, body2.y, 1); // plot body2 in red
cpgsci(3); // set line to colour green
cpgpt1(body3.x, body3.y, 1); // plot body3 in green
// usleep(100); // uncomment this line for larger time steps
}
usleep(100000000); // to prevent the plot from closing immediately
cpgend(); // end the plot
return 0;
}