A 3D n-body gravity simulation written in Python.
To get started, install all of the relevant packages with:
pip install -r requirements.txt
Next, just cd to the project's root directory and run:
py -m src.main # on windows
python3 -m src.main # on Unix/MacOS
To change the settings for the simulation, such as:
- the number of particles
- the number and size of the timesteps
- the maximum masses, distances, and speeds of the randomly-generated particles
- the number of points displayed in the final plot
- and more...
just check out and edit the contents of the config.yaml file in found in the .config/ folder.
- Config values are read from
config.yamlthat dictate how random particles are generated. - These values are used to generate
Particleobjects that store information about each particle's state - Gravity calculations are performed on a list of particles per timestep, while checks for collisions take place
- If collisions are found, collision groups are identified and 'merged' with the largest particle, with their momenta being conserved.
- Particle positions are read at slower than a per-timestep rate, derived from values in the config file.
- These particle positions are finally parsed and plotted in 3D using pyplot!
- Animation: I've already tried to get animations working but despite some success on a smaller scale, it's proving difficult to achieve with a dynamically set number of particles. Visuals of particles floating around and leaving behind a trail would surely be a massive improvement over what is currently on offer, but this is so far the best I've been able to achieve.
- Utilising more NumPy: Only after building confidence with libraries throughout this project have I realised just how much could be rewritten with greater use of
numpy. This version is itself essentially a complete overhaul that I managed to squeeze into less than a week, and yet I feel immediately that another one is already due. I was also proud of my creation of thepermutationsmodule that I made use of throughout, only to also eventually find thatitertoolsalready offers things likecombinationsandproductthat I could have been using. - Testing: The test suite I currently have is lacking in many ways but honestly I've been struggling to come up with a good way of testing what exactly is 'desired' about this simulation given the inherently flawed/approximative nature of numerical simulations. How much error is a reasonable amount of error? This is in itself dependent upon values for
dtandG, and even how many timesteps have passed. At the very least, I know that momentum and energy are approximately conserved locally, but 'global' tests would be nice. - Mass-based particle sizing: Seeing how straightforward it is to dynamically size the scatter points in pyplot (i.e. by just defining
s=), it immediately became apparent that if I kept some kind of parallel log of the mass (or the changes to it) then not only could I straightforwardly illustrate the masses of particles, but I could even dynamically change it when collisions with other particles occurred. - Particle arrangement presets: I orignally set out to make this thinking that I'd be able to hardcode the actual positions of the Sun, Earth and Moon to predict where they'll all be over time. The reality of that goal eventually set in and I figured that a general N-body simulation would be a good compromise. Having made it now though, I think it's probably not too hard to just add in a 'pre-configured particles' option that loads a preset that at the very least loosely resembles the motion of our solar system.
- Darkmode: I wanted to make the plots dark by default, but the default way of achieving this leaves the particle colours looking weirdly faded, but although this is something that's probably much easier to implement than the other improvements, I'm shelving it for now.
Thanks for reading! If you want to read a little bit more about the thought behind the code, check out docs/deep-dive.md.
Enjoy messing around with it! - Callum
