Newtonian N-body gravity simulator accelerated with C library
This is a student project developed for learning purpose. Other packages such as REBOUND are recommended for more functionality.
Features:
- Ten integrators including WHFast and IAS15
- Barnes-Hut algorithm
- GravitySimulator API (prototype)
- CUDA implementation for the pairwise acceleration function
- Multiple sample projects
TODOs (if I have time):
- Barnes-Hut algorithm with CUDA
- Quick Start
- Running the program in terminal
- Sample projects
- GravitySimulator API
- Default systems
- Integrators
- Making changes to saved systems
- Saving the results
- Output animations in .gif
- Compensated summation
- Feedback and Bugs
- Data Sources
- References
- Acknowledgement
This program requires Python version 3.10 or higher.
Download the source files, or clone this repository by running the following command in terminal:
git clone https://github.com/alvinng4/Gravity-Simulator
Install the required packages by
pip install .
If the installation is not successful, install the following packages manually:
matplotlib==3.8.3
numpy==1.26.4
rich==13.7.1
If the program failed to load the C library, you may choose the NumPy option (slow), or choose to recompile the C library. Simply go to the src folder and run
make [CC=gcc] [USE_CUDA=1]
Then, move the c_lib.dylib
, c_lib.dll
or c_lib.so
file into the gravity_sim folder (One of them will be generated depending on your operation system).
mv c_lib.dylib ../gravity_sim
mv c_lib.dll ../gravity_sim
mv c_lib.so ../gravity_sim
If you wish to use CUDA GPU acceleration, you will also need to recompile
the library with the USE_CUDA=1
flag, which requires nvcc
to be installed in your system.
- This project offers two user-interface: API and CLI
- The default unit for this project is solar masses, AU and days, with
$G = 0.00029591220828411956 \text{ M}_\odot^{-1} \text{ AU}^3 \text{ day}^{-2}$ . It is possible to change this value in the API by changingsystem.G
. - Animations, simulation results, etc. will be stored to
gravity_sim/result
by default, unless a file path is specified. - Complex animations like the asteroid belt cannot be done solely with the API functions. Sample scripts are provided in this repository (See Sample projects)
- Check the
examples
folder for API tutorial and sample projects - For WHFast, features including CUDA acceleration,
compensated_summation
,barnes-hut
andresume_simulation
are not available due to implementation difficulties and bugs.
Once you have downloaded the source files, navigate to the source directory in terminal and run
python gravity_sim [-n|--numpy]
-n, --numpy
: run the program with NumPy instead of C library
Some projects are done with the API. The scripts are stored at the examples
folder.
Videos:
Note: This simulation is for demonstration only. The initial conditions are very different from actual galaxies.
Videos:
You may import the GravitySimulator API from gravity_sim
to perform gravity simulation.
See examples/tutorial.ipynb
or Sample projects for some example usage.
If your computer cannot render jupyter notebook (files end with .ipynb
), you can view them on github.
from gravity_sim import GravitySimulator
grav_sim = GravitySimulator()
grav_sim.integration_mode = "c_lib" # "numpy" is also available
system = grav_sim.create_system()
grav_sim.set_current_system(system)
system.load("solar_system")
grav_sim.launch_simulation(
integrator="ias15",
tf=grav_sim.years_to_days(1000.0),
tolerance=1e-9,
store_every_n=50,
)
grav_sim.plot_2d_trajectory()
grav_sim.plot_rel_energy()
grav_sim.save_results()
launch_simulation() is the main method for launching the simulation.
Parameter | Type | Default | Description |
---|---|---|---|
integrator |
str | Required | Name of the integrator |
tf |
float | Required | Simulation time (days) |
dt |
float | None | Time step (days) |
tolerance |
float | None | Tolerance for adaptive step integrators |
store_every_n |
int | 1 | Store results every n steps |
acceleration_method |
str | pairwise |
Method for calculating accelerations |
storing_method |
str | default |
Method for storing simulation results |
flush_path |
str | None | Path to flush intermediate results. |
no_progress_bar |
bool | False | If True, disables the progress bar. |
no_print |
bool | False | If True, disables some printing to console |
softening_length |
float | 0.0 | Softening length for acceleration calculation |
**kwargs |
dict | - | Additional keyword arguments. |
euler
, euler_cromer
, rk4
, leapfrog
, rkf45
, dopri
, dverk
, rkf78
, ias15
, whfast
-
pairwise
- Brute force pairwise calculations for gravitational acceleration
- Time complexity:
$O(N^2)$ - Variants:
pairwise_cuda
,pairwise_float_cuda
,pairwise_float_comp_sum_cuda
(Not available forWHFast
)- Parallelized calculation with CUDA GPU acceleration.
-
pairwise_float_cuda
uses single precision to provide furthur speed up with a loss of precision -
pairwise_float_comp_sum_cuda
uses compensated summation to reduce precision loss (See Compensated summation)
-
massless
- Similar to
pairwise
, but seperate the calculations for massive and massless particles - Time complexity:
$O(M^2 + MN)$ , where$M$ and$N$ are the number of massive and massless particles respectively
- Similar to
-
barnes-hut
- Calculate gravitational acceleration with barnes-hut algorithm
- Time complexity:
$O(N \log{N})$ -
**kwargs
:barnes_hut_theta
- Threshold for Barnes-hut algorithm, default = 0.5
default
- Store solutions directly into memory
flush
- Flush intermediate results into a csv file in
gravity_sim/results
to reduce memory pressure.
- Flush intermediate results into a csv file in
no_store
- To not store any result, typically used for benchmarking.
Some systems are available by default.
System | Description |
---|---|
circular_binary_orbit | A circular orbit formed by two stars |
eccentric_binary_orbit | An eccentric orbit formed by two stars |
3d_helix | An upward helix consists of three stars |
sun_earth_moon | The Sun, Earth, and Moon system |
figure-8 | A "figure-8" orbit involving three stars |
pyth-3-body | Three stars arranged in a triangle with length ratios of 3, 4, and 5. It is a highly chaotic orbit with close encounters that can be used to test the difference between fixed and variable step size integrators. |
solar_system | Solar System with the Sun and the planets |
solar_system_plus | solar_system with the inclusion of Pluto, Ceres, and Vesta |
Below are four simple fixed step size methods to simulate the system with a given step size
Simple methods |
---|
Euler |
Euler Cromer |
Fourth Order Runge-Kutta (RK4) |
Leapfrog |
Embedded RK methods are adaptive methods that decides the step size automatically based on the estimated error. It can resolve close encounters but fail to conserve energy over long time scele.
Embdedded Runge-Kutta methods | Recommended tolerance* |
---|---|
Runge–Kutta–Fehlberg 4(5) |
|
Dormand–Prince method (DOPRI) 5(4) |
|
Verner's method (DVERK) 6(5) |
|
Runge–Kutta–Fehlberg 7(8) |
|
*For reference only
IAS15 (Implicit integrator with Adaptive time Stepping, 15th order) is a highly optimized integrator with extremely high accuracy. It is the default method for this project.
The recommended tolerance* is
*For reference only
WHFast is a second order symplectic method with fixed step size, which conserves energy over long integration period. This integrator cannot resolve close encounter.
Argument | Description | Default Value |
---|---|---|
kepler_tol |
Tolerance in solving the Kepler's equation | |
kepler_max_iter |
Maximum number of iterations in solving Kepler's equation | 500 |
kepler_auto_remove |
Integer flag to indicate whether to remove objects that failed to converge in Kepler's equation | False |
kepler_auto_remove_tol |
Tolerance for removing objects that failed to converge in Kepler's equation |
Warning
When using WHFast, the order of adding objects matters. Since WHFast use Jacobi coordinate, we must add the inner object first, followed by outer objects relative to the central star. For convenience, you may also add the objects in any order, then call system.sort_by_distance(primary_object_name)
or system.sort_by_distance(primary_object_index)
If you wish to make any changes to saved systems, you can access the file at
gravity_simulator/gravity_sim/customized_systems.csv
The data follow the format
Name, Gravitational constant, Number of objects, m1, ..., x1, y1, z1, ..., vx1, vy1, vz1, ...
You may also load the system in API and then save the system after making the changes.
If you saved the results, the numerical data will be stored in the following folder:
Gravity-Simulator/gravity_sim/results
The file will starts with the metadata which starts with #
.
Missing information will be saved as None
.
More rows may be added in the future.
Below is an example:
# Data saved on (YYYY-MM-DD): 2024-07-27
# System Name: solar_system
# Integrator: IAS15
# Number of objects: 9
# Gravitational constant: 0.00029591220828411956
# Simulation time (days): 73048.4378
# dt (days): None
# Tolerance: 1e-09
# Data size: 64596
# Store every nth point: 1
# Run time (s): 1.4667500000214204
# masses: 1.0 1.6601208254589484e-07 2.447838287796944e-06 3.0034896154649684e-06 3.2271560829322774e-07 0.0009547919099414248 0.00028588567002459455 4.36624961322212e-05 5.151383772654274e-05
Then, the actual data will be saved in the default unit (solar masses, AU and days), and follow this format:
time, dt, total energy, x1, y1, z1, ... vx1, vy1, vz1, ...
The saved data file can be read by the program. Even if the metadata is corrupted or missing, the program can still read the data file, although some information could be missing.
You may output the simple trajectory animations in 2D / 3D in .gif.
The output file would be stored in gravity_sim/result
.
Available parameters:
Parameter | Description |
---|---|
FPS | Frames per second |
Animation length | Desired length of the output gif |
plot_every_nth_point | File name without extension |
dpi | The resolution of the animation (dots per inch) |
is_dynamic_axes | Rescale the axes limit dynamically |
axes_lim | An array for the axes limits |
is_maintain_fixed_dt | Attempt to maintain fixed step size with variable time step data |
traj_len | Length of the trajectory in number of data points |
Some parameters are not listed here due to limit of space.
A method known as compensated summation [1], [4] is implemented for all integrators EXCEPT WHFast:
When we advance our system by
Since
However, for WHFast, the improvement is little but takes 10% longer run time. Therefore, it is excluded from this method.
If you find any bugs or want to leave some feedback, please feel free to let me know by opening an issue or sending an email to [email protected].
The solar system positions and velocities data at 1/Jan/2024 are collected from the Horizons System [2]. Gravitational constant, and masses of the solar system objects are calculated using the data from R.S. Park et. al. [3].
- E. Hairer, C. Lubich, and G. Wanner, "Reducing Rounding Errors" in Geometric Numerical Integration: Structure-Preserving Algorithms for Ordinary Differential Equations. Springer, 2004, pp. 272-274.
- Horizons System, Jet Propulsion Laboratory, https://ssd.jpl.nasa.gov/horizons/
- R. S. Park, et al., 2021, “The JPL Planetary and Lunar Ephemerides DE440 and DE441”, https://ssd.jpl.nasa.gov/doc/Park.2021.AJ.DE440.pdf, Astronomical Journal, 161:105.
- H. Rein, and D. S. Spiegel, 2014, "IAS15: A fast, adaptive, high-order integrator for gravitational dynamics, accurate to machine precision over a billion orbits", Monthly Notices of the Royal Astronomical Society 446: 1424–1437.
The integrators in this project were developed with great assistance from the following book:
- J. Roa, et al. Moving Planets Around: An Introduction to N-Body Simulations Applied to Exoplanetary Systems, MIT Press, 2020