Grains in a turning drum avalanche and sort themselves: big outside, small in the core.
About a thousand disks are simulated with the discrete element method: overlapping grains feel a spring and damper, Coulomb friction along the contact twists them, and a little rolling resistance stands in for grain angularity, while studs on the drum wall drag the pile up until it avalanches. In the thin flowing layer at the surface, small grains fall through the gaps between big ones and get buried, and the big grains (also half as dense here, like plastic beads among glass) ride over the top, so within a few turns the small grains gather into a core inside a ring of big ones. The flow regime follows the Froude number omega^2 R / g: slumping avalanches, a steady rolling sheet, an S-shaped cascade, grains flung through the air, and finally everything pinned to the wall. A sparkline tracks how segregated the bed is.
Try it. Drag the speed slider or press 1 to 5 to jump between slumping, rolling, cascading, cataracting and centrifuging, or nudge it with the arrow keys. Drag inside the drum to stir with a paddle. Press M for a mixed fill, L for alternating layers that wind into spirals, T for three sizes, and V to make fast-flowing grains glow.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a rotating drum full of colored grains, simulated with the discrete element method, with JavaScript and the HTML canvas element. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.
Start simple:
- Make a canvas that fills the window, stays sharp on high-DPI screens (scale by devicePixelRatio), and resizes with the window. Draw a large circular drum in the middle on a dark background.
- Fill the bottom half of the drum with about 400 disks: half small (blue) and half twice as large (orange), with a little random variation in size so they never pack into a perfect lattice.
- Each disk has a position, velocity, spin and mass. Where two disks overlap, push them apart with a spring proportional to the overlap plus a damper on their approach speed, and add friction along the contact that never exceeds 0.5 times the normal force. Friction also spins both disks.
- The drum wall is a circle that moves with the drum's rotation, so its friction drags grains up the side.
- Add gravity and integrate with many small time steps per frame (around 50), so contacts stay stable.
- Draw each grain as a shaded circle and rotate a few marks on the drum so you can see it turn.
Once that works, make it beautiful:
- Speed up contact detection with a uniform grid rebuilt every step.
- Add a little rolling resistance so piles hold a realistic slope.
- Let the arrow keys change the rotation speed, and show the Froude number omega^2 R / g with the regime it implies: slumping, rolling, cascading, cataracting or centrifuging.
- Let the mouse stir the grains with a round paddle, and add a mode that fills the drum in alternating layers so you can watch the flow wind them into spirals.
Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as measuring a segregation index over time, adding a third grain size, or adding ribs to the drum wall.