Astrophysics · Cosmology
📅 July 2026 ⏱ ≈ 13 min read 🎯 Intermediate · Last updated: 9 July 2026

Dark Matter — galaxy rotation curves and the evidence for invisible mass

Stars at the edge of a spiral galaxy orbit almost as fast as stars near its centre — something that should be impossible if the visible stars and gas were all the mass there is. The mismatch is the single strongest piece of evidence for dark matter, and it's simple enough to reproduce with a rotation-curve calculator and a Three.js halo.

TL;DR: Spiral galaxies rotate almost flat instead of slowing down at the edges, which means far more mass is hiding in an extended halo than we can see in stars and gas. Vera Rubin's measurements confirmed this pattern; the NFW halo profile models it, and MOND is a rival explanation that modifies gravity instead of adding mass.

1. What is a rotation curve?

A galaxy rotation curve is a plot of the orbital speed of stars and gas clouds against their distance from the galactic centre. Astronomers measure it using the Doppler shift of the 21 cm hydrogen line: gas moving toward us is blue-shifted, gas moving away is red-shifted, and the shift's magnitude gives the line-of-sight velocity at each radius.

If the only mass in a galaxy were the stars, gas and dust we can photograph, the rotation curve should fall off the same way planets in the Solar System do: fast near the centre, slower further out. That is not what is observed.

Scale reminder: the Sun orbits the Milky Way's centre at roughly 220 km/s, at a radius of about 27 000 light-years. If the galaxy's mass were concentrated the way its light is, stars twice as far out should move noticeably slower — they don't.

2. The Newtonian expectation

For a test mass orbiting a spherically symmetric distribution of mass M(r) enclosed within radius r, Newtonian gravity predicts a circular orbital speed of:

v(r) = √(G · M(r) / r)

Beyond the edge of the visible disk, M(r) stops growing — almost all the light-emitting matter is inside a fairly well-defined radius. So M(r) becomes roughly constant, and the formula predicts:

v(r) ∝ 1/√r ← Keplerian decline, like planets around the Sun

This is exactly how the outer planets of the Solar System behave: Neptune orbits far slower than Mercury, because almost all the Solar System's mass (the Sun) is concentrated at the centre. Applying the same logic to a galaxy, the rotation curve should fall past the edge of the visible disk.

3. Vera Rubin and the flat curve

In the 1970s, astronomer Vera Rubin, working with Kent Ford, measured the rotation curves of dozens of spiral galaxies using a sensitive spectrograph. Instead of the expected Keplerian decline, she found that rotation curves stayed flat — sometimes even rising slightly — far beyond the edge of the visible disk.

Rubin's work, building on earlier hints from Fritz Zwicky's 1933 study of the Coma galaxy cluster, turned dark matter from a speculative footnote into one of the central problems of modern astrophysics. Independent evidence — gravitational lensing, galaxy cluster dynamics, and the cosmic microwave background — has since converged on the same conclusion.

Numbers: observed rotation curves imply that spiral galaxies contain roughly 5–10 times more mass in dark matter than in ordinary (baryonic) matter — stars, gas and dust combined.

4. The mass-velocity relationship

Rearranging the orbital speed formula lets us go the other way: given an observed flat velocity v, work out how the enclosed mass must grow with radius.

v(r) = √(G · M(r) / r)  →  M(r) = v² · r / G

If v(r) = v₀ = constant (flat curve)
then M(r) ∝ r  ← mass grows linearly with radius, not bounded

A mass that grows linearly with radius, with the density falling off as ρ(r) ∝ 1/r², describes an isothermal sphere — a simple first model of a dark matter halo. It reproduces flat rotation curves almost by construction, which is exactly why it became the starting point for more detailed halo models.

// Given an assumed density profile rho(r), integrate to get enclosed mass
function enclosedMass(r, densityFn, steps = 200) {
  let M = 0;
  const dr = r / steps;
  for (let i = 0; i < steps; i++) {
    const ri = (i + 0.5) * dr;
    M += 4 * Math.PI * ri * ri * densityFn(ri) * dr;
  }
  return M;
}

function orbitalVelocity(r, densityFn, G = 6.674e-11) {
  const M = enclosedMass(r, densityFn);
  return Math.sqrt(G * M / r);
}

5. The NFW halo profile

N-body cosmological simulations of structure formation (Navarro, Frenk & White, 1996) found that cold dark matter halos settle into a remarkably universal density shape, now called the NFW profile:

ρ(r) = ρ₀ / [ (r/rₛ) · (1 + r/rₛ)² ]

ρ₀ — characteristic density
rₛ — scale radius (where the slope transitions)

Near the centre (r ≪ rₛ) the density diverges as 1/r — a steep "cuspy" core that is still debated versus flatter "cored" profiles suggested by some dwarf galaxy observations (the core–cusp problem). Far out (r ≫ rₛ) the density falls as 1/r³, steeper than the isothermal sphere, which is why real rotation curves gently decline at very large radii instead of staying perfectly flat forever.

Component Mass share Extent Rotation-curve role
Stars + gas (baryons) ~10–15% Visible disk, ~50k ly Dominates inner rise
Dark matter halo ~85–90% Extends to ~300k ly+ Keeps the curve flat

6. The alternative: MOND

Modified Newtonian Dynamics (MOND), proposed by Mordehai Milgrom in 1983, takes a different route: instead of adding unseen mass, it modifies the law of gravity itself at very low accelerations (below roughly a₀ ≈ 1.2 × 10⁻¹⁰ m/s²). In that regime, MOND replaces F = ma with a modified relation that naturally produces flat rotation curves without any dark matter.

MOND fits individual galaxy rotation curves impressively well with very few free parameters, but it struggles to explain cluster-scale gravitational lensing and the detailed structure of the cosmic microwave background, both of which fit a cold dark matter model cleanly. Most cosmologists treat dark matter as the leading explanation, with MOND remaining an active but minority research program.

Caveat: this article's simulation approximates the standard dark-matter-halo picture. It is a pedagogical model, not a precision fit to any specific real galaxy's measured curve.

7. Simulating a halo in Three.js

The dark matter simulation on this site renders a luminous stellar disk (visible, bright, InstancedMesh — the same technique used for the spiral-arms simulation) surrounded by a much larger, mostly invisible halo of "dark" particles following an NFW-like radial distribution. A live rotation-curve graph is drawn alongside, comparing the "stars-only" Keplerian prediction against the flat curve produced once the halo's gravity is included.

// Sample halo particle radii following an NFW-like profile via inverse CDF sampling
function sampleNFWRadius(rs, rMax) {
  // Rejection sampling: draw r uniformly, accept with probability proportional to r^2 * rho(r)
  while (true) {
    const r = Math.random() * rMax;
    const x = r / rs;
    const weight = (r * r) / (x * Math.pow(1 + x, 2));
    const wMax = rs * rs * 0.25; // rough normalising bound
    if (Math.random() * wMax < weight) return r;
  }
}

// Halo particles: faint, additive-blended, mostly transparent
const haloMat = new THREE.PointsMaterial({
  size: 0.6,
  color: 0x6a5acd,
  transparent: true,
  opacity: 0.05,
  blending: THREE.AdditiveBlending,
  depthWrite: false,
});

The rotation curve overlay is drawn on a 2D canvas overlay (or an HTML <canvas> chart library) rather than in the 3D scene — mixing a precise data plot with a WebGL viewport keeps both readable, instead of forcing numeric labels into 3D space.

// Two curves: stars-only Keplerian decline vs stars+halo flat curve
function drawRotationCurve(ctx, starsMass, haloMass, rMaxDraw) {
  ctx.beginPath();
  for (let r = 1; r < rMaxDraw; r++) {
    const vStarsOnly = orbitalVelocity(r, starsMass);
    // plot vStarsOnly(r) — dashed line, falls off past disk edge
  }
  ctx.beginPath();
  for (let r = 1; r < rMaxDraw; r++) {
    const vTotal = orbitalVelocity(r, (rr) => starsMass(rr) + haloMass(rr));
    // plot vTotal(r) — solid line, stays flat
  }
}

8. Extensions and improvements

🌑 Dark Matter

The live simulation renders a stellar disk plus an invisible NFW-like halo, with a real-time rotation-curve graph comparing stars-only vs stars+halo predictions.

Launch simulation →