# ✨ Heavens Run N-Body simulations with your GPU:

## 📦 Dependencies - [Rust compiler](https://www.rust-lang.org/tools/install) ## 🚀 Quickstart Clone the repository and set your working directory to the root of the project: ```shell git clone https://github.com/FreddyWordingham/heavens.git cd heavens ``` Build the project in release mode: ```shell cargo build --release ``` Run the program: ```shell cargo run --release ```

## 🎮 Controls | Letter | Description | | ------- | ----------------------------------- | | `-` | Halve timestep | | `=` | Double timestep | | `Q` | Decrease Zoom | | `E` | Increase zoom | | `Z` | Halve the blur radius | | `X` | Double the blur radius | | `F` | Decrease strength of gravity | | `G` | Increase strength of gravity | | `A` | Spin camera anticlockwise | | `D` | Spin camera clockwise | | `W` | Turn simulation towards camera | | `S` | Turn simulation away from camera | | `O` | Halve ghost stack visibility limit | | `P` | Double ghost stack visibility limit | | `Space` | Pause / Unpause Time | ## 📝 Usage I will create a runtime TOML configuration scheme in the future. For now you can use `heavens`as a library to design your own N-Body simulations: 1. You'll need these imports: ```rust use heavens::{run, Camera, NBody, Settings}; ``` 2. Initialise your settings: ```rust fn init_settings() -> Settings { Settings { display_width: 1300.0, // [pixels] display_height: 1300.0, // [pixels] pixel_size: 1.0, // [screen pixel per simulation pixel] gravitational_constant: 1.0, // [m^3 kg^-1 s^-2] time_step: 1.0e1, // [s] smoothing_length: 1.0, // [m] ghost_mass: 1.0, // [kg] ghost_stack_visible_limit: 4.0, // This many ghosts on top of each other will have an alpha of 1.0 blur_radius: 5.0, // [pixels] } } ``` 3. Initialise your camera: ```rust fn init_camera() -> Camera { let eye_pos = [1.0e3, 0.0, 1.0e3]; // [m] let tar_pos = [0.0, 0.0, 0.0]; // [m] let field_of_view = 90.0_f32.to_radians(); // [radians] let zoom = 1000.0; // [m] Camera::new(eye_pos, tar_pos, field_of_view, zoom) } ``` 4. Now the fun part, initialise the initial conditions of your simulation: ```rust fn init_conditions(grav_const: f32) -> NBody { let mut rng = rand::thread_rng(); let mut init_conditions = NBody::new(); // Construct an empty NBody simulation init_conditions.add_massive_system( &mut rng, grav_const, // gravitational constant [m^3 kg^-1 s^-2] [0.0, 0.0, 0.0], // centre [m] [0.0, 0.0, 0.0], // drift [m/s] 1.0e3, // radius [m] 1.0e1, // centre mass [kg] 1.0e-1, // disc mass [kg] (64 * 64) - 1, // num particles ); init_conditions.add_ghost_field( &mut rng, [0.0, 0.0, 0.0], // centre [m] [0.0, 0.0, 0.0], // drift [m/s] 1.0e3, // radius [m] 1.0e1, // central mass [kg] 655 * 64 * 4, // num particles 5.0, // kind (used to colour particles) ); // More bodies here... init_conditions } ``` 5. Write the main function: ```rust fn main() { env_logger::init(); pollster::block_on(start()); } async fn start() { println!("Initialising settings..."); let settings = init_settings(); println!("Initialising camera..."); let camera = init_camera(); println!("Generating initial conditions..."); let init_conditions = init_conditions(settings.gravitational_constant); println!("Initial conditions generated.\nRunning simulation..."); run(settings, camera, init_conditions).await; } ``` See the example [`main.rs`](./src/main.rs) for a more complete example. ## 📚 Documentation Find the documentation at https://docs.rs/heavens/ ## 🌌 TODO - [x] Initial conditions helper class - [x] Ghost particles - [x] Colored particles - [x] Camera controls - [ ] Write docstrings - [ ] Runtime parameterisation - [ ] No-window (capture) mode