2D Simulation of the Solar System by numerically solving the equations of motion for the planets.
To simulate the planets' motion, we first need to find the equation of motion and solve it. We could directly use the Keplerian solution of the motion but i'd rather use a numerical method and considering the precession of Mercury's perihelion
The equation of motion is given with Newton's second law
In cartesian coordinates, the equation becomes 2 equations :
-
$\displaystyle \frac{dv_x}{dt} = \frac{d^2x}{dt^2} = -\frac{GM}{r^2} \cos(\theta)$ where$\displaystyle \cos(\theta) = \frac{x}{r}$ -
$\displaystyle \frac{dv_y}{dt} = \frac{d^2y}{dt^2} = -\frac{GM}{r^2} \sin(\theta)$ where$\displaystyle \sin(\theta) = \frac{y}{r}$
where
$\displaystyle \frac{d^2x}{dt^2} = -GM\frac{x}{(x^2 + y^2)^{3/2}} $ $\displaystyle \frac{d^2y}{dt^2} = -GM\frac{y}{(x^2 + y^2)^{3/2}}$
For Mercury, the precession is
-
$\displaystyle \frac{dv_x}{dt} = -GM \frac{x}{r^3}$ +$\displaystyle \dot{\phi} \frac{dy}{dt}$ -
$\displaystyle \frac{dv_y}{dt} = -GM \frac{y}{r^3}$ -$\displaystyle \dot{\phi} \frac{dx}{dt}$
I first need to give the differents parameters for each planet (Name, distance from the Sun, ellipticity, color and the size) :
params = {
'Mercury': (57.91e9, 0.2056, 'gray', 0.13),
'Venus': (108.2e9, 0.0068, 'yellow', 0.5),
'Earth': (1.496e11, 0.0167, 'royalblue', 0.5),
'Mars': (227.9e9, 0.0934, 'red', 0.4),
'Jupiter': (778.3e9, 0.049, 'orange', 1.5),
'Saturn': (1.42e12, 0.056, 'gold', 1.3),
'Uranus': (2.87e12, 0.046, 'lightseagreen', 0.8),
'Neptune': (4.5e12, 0.010, 'blue', 0.8)
}
Once the system of equations is defined, I need to choose the initial conditions for each planet based on the parameters. The initial conditions are determined by the initial distance, which is the semi-major axis
initial_conditions = {planet: [a * (1 - e), 0, 0, v(a, planet)] for planet, (a, e, _, _) in params.items()}
Then, we numerically solve the equations of motion for each planet using odeint from the scipy library. We create a large yellow dot representing the Sun and place it at the center of the plot.
The goal is to generate the motion of the planets and plot their trajectories to clearly observe their orbits. We also include a timer in years (based on Earth's orbit). For each time step, we plot the new position of each planet
def animate(i):
for (planet, solution, line, planet_point, trail) in zip(params, solutions.values(), lines, planets, trails):
x = solution[i, 0]
y = solution[i, 1]
line.set_data(x, y)
planet_point.set_data(x, y)
trail.set_data(solution[:i, 0], solution[:i, 1])
sun.set_offsets([0, 0])
# Update time in years
years_elapsed = t_values[i] / (365.25 * 24 * 60 * 60) # Convert to years
time_text.set_text(f'Time elapsed: {years_elapsed:.2f} years')
return lines + planets + trails + [sun, time_text]
We animate the motion using FuncAnimation from the matplotlib.animation library. Here are screenshots of the simulation
![image](https://private-user-images.githubusercontent.com/140922475/303174203-1aa5cc5d-84fa-43ad-91c3-39e60f23185c.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQ1ODMzNDYsIm5iZiI6MTcyNDU4MzA0NiwicGF0aCI6Ii8xNDA5MjI0NzUvMzAzMTc0MjAzLTFhYTVjYzVkLTg0ZmEtNDNhZC05MWMzLTM5ZTYwZjIzMTg1Yy5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwODI1JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDgyNVQxMDUwNDZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0zOWMxNmIzNGFiMDhlMWNjODE1MzY1ZTAyMGZhNGNlYzY1Yjc3NTg4NTFmMWE2MzU4MjA3M2ZjZWFjNWZlYmFkJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.mQ7xemEB_tGQ6JphbPkQe9SCV2kxKoQa-XNnB2lnSQQ)
![image](https://private-user-images.githubusercontent.com/140922475/303174325-0e627381-3d16-4abd-bafc-51fdfed01820.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQ1ODMzNDYsIm5iZiI6MTcyNDU4MzA0NiwicGF0aCI6Ii8xNDA5MjI0NzUvMzAzMTc0MzI1LTBlNjI3MzgxLTNkMTYtNGFiZC1iYWZjLTUxZmRmZWQwMTgyMC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwODI1JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDgyNVQxMDUwNDZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0wZjg5NTA3ZjA3YjU3MTg3MmE3YTI0MWM0OWI5ZTFlYzRkZDJjMjk3OGFhYzcyYWMzMGI1M2ZkYzY5MDA1NDgzJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.ywPgrHkOoyb7L-yLbpZSoi6zjS1iJLQDLS_aixZ9eE8)
![image](https://private-user-images.githubusercontent.com/140922475/303174430-8501f7d6-527e-4c95-84e0-b27e7086279f.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQ1ODMzNDYsIm5iZiI6MTcyNDU4MzA0NiwicGF0aCI6Ii8xNDA5MjI0NzUvMzAzMTc0NDMwLTg1MDFmN2Q2LTUyN2UtNGM5NS04NGUwLWIyN2U3MDg2Mjc5Zi5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwODI1JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDgyNVQxMDUwNDZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT03ZWFkNGI3ODcxY2E2MzNmOTZhZGFmZTYzZjk4N2ViZjljZTY2NWQwMjg1YWNiMjkxMzU3YWY5ZTM4Nzk0YTNkJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.2EgGBZrHPuvEh5vLhEt9jVOc8ehUY_zcnfeXL70kYyo)