Skip to content
Will Roscoe edited this page Jun 15, 2024 · 12 revisions

nBody Macroscopic Physics Simulation

The goal of this project is to efficiently simulate the gravitational and kinetic interactions between physical objects and display them in a user friendly interface. The usage of this project is Object Oriented and mean't to be flexible and easy to use.

Warning

This Wiki is not regularly updated. this page was last checked for accuracy on 8th December 2023.

Note

This Wiki is updated for v2.0 of the Project. To access this, please go to the main branch. v3.0 will be targetting optimization and will be a lot more specific in usage and will aim to utilise multiprocessing and Barnes-Hut Algorithm.


Required Packages:

math, re, datetime, decimal, (Built in)

tqdm, numpy, matplotlib, astroquery,astropy, pint, mpmath, pandas,

pytest is in requirements for testing purposes

scipy is recommended but optional.

gmpy2 is a requirement but can be excluded, note this will severely decrease efficiency of non float calculations using mpmath.


Overview

There are 3 main objects which a user would interact with while creating a simulation, these are:

  • Body : Representation of a physical object

  • Engine : Representation of a system of Body objects and comuputes the physics.

  • MPLVisual : Controls the output and the runtime of a Engine object.

A typical script to simulate a box with 4 balls:

balls = (Body(3,(0,-1,1),(0,0.6,-0.01), 0.1, identity='ball1', color='yellow'),
        Body(3,(0,1,0),(0.2,-0.5,-0.5), 0.1, identity='ball2', color='magenta'),
        Body(3,(1,0,0),(-0.2,0.1,0.1), 0.1, identity='ball3', color = 'orange'),
        Body(3,(0,-1,0),(-0.6,0.05,1), 0.1, identity='ball4', color='gold')
)
  • Here we create an array of our objects as Body instances, containing their unique position and velocity at the start of the simulation, and each has a radius of 0.1 and is assigned a name and color.
engine = Engine(dt=0.01)
engine.attach_bodies(balls)
engine.do_bodygravity, engine.do_fieldgravity = False, False
  • We then initialise a Physics Engine instance with a time interval of 0.01 seconds and put the bodies array into the engine.
((engine.create_plane(ax, num) for num in (-1.2, 1.2)) for ax in ('x', 'y', 'z'))
  • After that we have generate 6 planes using Engine().create_plane() to act as the sides to our box. each side is 1.2 (metres) from the origin.
sim = MPLVisual(name='Balls in a Box', autoscale=False, focus_body=None, focus_range=1.2, body_model='surface', eval_length=10000, fps=30, frameskip=10, plotskip=10)
  • Next we initialise a Simulation instance, which holds the name of the simulation and several parameters pertaining to the style and type of output you will get:
    • focus_range=1.2 sets the axes to 1.2, meaning that the axes will only extend to the box.
    • body_model='surface' makes the simulation render a spherical surface with the body radius.
sim.start()
  • Lastly we start the simulation by MPLVisual().start(). the arguments of this function define the amount of intervals to evaluate, the speed of the animation and the intervals controlling which frames and points to drop, i.e, frameskip=2 would drop every second frame so the outputted animation would be 2 times faster.
Screenshot of Output:
Full Code:
balls = (Body(3,(0,-1,1),(0,0.6,-0.01), 0.1, identity='ball1', color='yellow'),
         Body(3,(0,1,0),(0.2,-0.5,-0.5), 0.1, identity='ball2', color='magenta'),
         Body(3,(1,0,0),(-0.2,0.1,0.1), 0.1, identity='ball3', color = 'orange'),
         Body(3,(0,-1,0),(-0.6,0.05,1), 0.1, identity='ball4', color='gold'))
engine = Engine(dt=0.01)
engine.attach_bodies(balls)
((engine.create_plane(ax, num) for num in (-1.2, 1.2)) for ax in ('x', 'y', 'z'))
sim = MPLVisual(name='Balls in a Box', autoscale=False, focus_body=None, focus_range=1.2, body_model='surface')
sim.start(eval_length=10000, fps=30, frameskip=10, plotskip=10)