Uran & Elyssa
I've been thinking about how we could build a simple simulation of galaxy formation that both visualizes the process and teaches students about dark matter, and I was wondering what tools youād think would make that most accessible.
Hey, thatās a cool ideaāletās keep it light and handsāon so students can see the math in action. Iād start with a webābased stack: use Three.js for 3āD rendering and maybe a small physics engine like Cannon.js or even a custom Nābody solver in JavaScript; that way everyone can just drop the HTML into a browser. Pair it with D3 for the darkāmatter heatmap overlay and a simple UI to tweak parameters. If you want something more codeāheavy, a Python Jupyter notebook with Matplotlib for 2āD slices and a tiny Nābody routine written in NumPy is perfect for showing the math under the hood. For a slick, interactive demo, Unity or Godot let you drop in a visual script and hit publish. Pick the tool that matches your teamās skill level and your timelineādonāt overāengineer it, or youāll lose the ālearning by doingā vibe.
Sounds solidāThree.js with a lightweight Nābody routine is probably the sweet spot. You can keep the code in plain JavaScript so students see the math and physics without needing a heavy build system, and the D3 overlay will let them visualize the darkāmatter distribution in real time. If the team already knows Python, a small Jupyter notebook with NumPy is just as effective, but the web stack keeps it truly handsāon for most learners.
That plan feels just rightāno heavy tooling, just the core math and a splash of color with D3. Students will love watching gravity play out in real time and instantly seeing the darkāmatter halo pop up. You can keep the Nābody loop tiny, maybe a simple velocityāVerlet, and then feed the positions straight into Three.js meshes. A slider to tweak the darkāmatter fraction would let them see how the invisible mass scaffolds everything. Keep the code clean, comment the equations, and youāve got a live, interactive textbook in a browser. Letās prototype a singleāparticle demo first and then scale upākeeps the momentum going and the debugging fun.
Sounds like a planāstart with a single particle and watch how its orbit stabilizes, then add another and watch chaos creep in. Itās a nice way to see the math in action, and the slider for the darkāmatter fraction will give students that āahaā moment. Keep the code tidy, comment the equations, and youāll have a live textbook in the browser. Let's roll.
Alright, letās fire up the sandbox and code that singleābody orbit firstāthen double it up and let the chaos show. Iāll set up the basic Nābody loop in plain JavaScript, wire it to Three.js, and add a D3 overlay that reacts to the darkāmatter slider. Weāll keep the math in comments, so the students see every step. Ready to push the first line?
Sure, letās start with a very simple version.
```js
// 1ābody orbit in 2āD using velocityāVerlet
const G = 1; // gravitational constant (arbitrary units)
let pos = [1, 0]; // initial position (x, y)
let vel = [0, 1]; // initial velocity
const dt = 0.01; // time step
function step() {
// compute acceleration: a = -G * m / r^3 * r
const r = Math.hypot(pos[0], pos[1]);
const a = [-G * pos[0] / r ** 3, -G * pos[1] / r ** 3];
// update velocity
vel[0] += a[0] * dt;
vel[1] += a[1] * dt;
// update position
pos[0] += vel[0] * dt;
pos[1] += vel[1] * dt;
// render with Three.js / D3 here
}
setInterval(step, dt * 1000);
```
Thatās the bare minimum. Once youāre happy with the orbit, double the mass and add the second particle, then watch chaos creep in.
Nice starting point! A couple quick tweaks will keep the physics stable and give you a clean way to stack more bodies.
1. Move `dt` out of `setInterval`. Pass it directly to `step()` so you can change it without reāsetting the interval:
```
function step(dt) {
// ⦠same as before
}
setInterval(() => step(dt), dt * 1000);
```
2. Keep a small epsilon in your distance check so you never divide by zero when a particle comes too close to the center.
3. Store each bodyās position and velocity in an array of objects; that way you can loop over them later instead of hardācoding the second one.
4. For the second body, give it a slightly different initial radius or velocity so it doesnāt sit exactly on the same orbitāmaybe 1.2 units out and a tangential speed 0.9Ć the first.
5. After you confirm the singleābody ellipse looks right, add a loop to update all bodies in each tick:
```
function step(dt) {
for (let b of bodies) {
const r = Math.hypot(b.x, b.y);
const ax = -G * b.x / r**3;
const ay = -G * b.y / r**3;
b.vx += ax*dt;
b.vy += ay*dt;
b.x += b.vx*dt;
b.y += b.vy*dt;
}
}
```
That structure will let you keep the code tidy while scaling up to more particles. When you add the second mass, watch how the trajectory starts to wobbleāperfect for that āchaos creeps inā moment. Good luck!