Fragmentation
Quick Start
Break some spaghetti, a glass tube, a sugar cube or just about any brittle object and the sizes of the fragments are distributed with a characteristic number-to-size ratio, depending on the dimensionality of the object. It applies to stone-age tools and space-age materials. The general formula has been known for many years, but the science behind it emerged in Nov 2025.
Credits
The formulae were derived by Emmanuel Villermaux in Fragmentation: Principles versus Mechanisms, Phys. Rev. Lett. 135, 228201 .
Universal Fragmentation
"use strict";
//One universal basic required here to get things going once loaded
window.onload = function () {
//restoreDefaultValues(); //Un-comment this if you want to start with defaults
Main();
};
//Main() is hard wired as THE place to start calculating when inputs change
//It does no calculations itself, it merely sets them up, sends off variables, gets results and, if necessary, plots them.
function Main() {
//Save settings every time you calculate, so they're always ready on a reload
saveSettings();
//Send all the inputs as a structured object
//If you need to convert to, say, SI units, do it here!
const inputs = {
Min: sliders.SlideMin.value,
nMin: sliders.SlidenMin.value,
Max: sliders.SlideMax.value,
D: sliders.SlideD.value,
};
//Send inputs off to CalcIt where the names are instantly available
//Get all the resonses as an object, result
const result = CalcIt(inputs);
//Set all the text box outputs
document.getElementById('beta').value = result.beta;
//Do all relevant plots by calling plotIt - if there's no plot, nothing happens
//plotIt is part of the app infrastructure in app.new.js
if (result.plots) {
for (let i = 0; i < result.plots.length; i++) {
plotIt(result.plots[i], result.canvas[i]);
}
}
//You might have some other stuff to do here, but for most apps that's it for Main!
}
//Here's the app calculation
function CalcIt({ Min, nMin, Max,D}) {
const nSteps = 100
let beta=1.3
if (D==2) beta=2.4
if (D==3) beta=3.5
let i,FPlot = [],size
//FPlot.push({ x: Min, y: nMin })
for (i = 0; i < nSteps; i++) {
size=Min+i*(Max-Min)/nSteps
FPlot.push({ x: size, y: nMin*((size/Min)**-beta)})
}
//Integrated/=Bzcm.length
const plotData = [FPlot]
const lineLabels = ["n"]
const myColors = ["blue"]
const borderWidth = [2]
//Now set up all the graphing data detail by detail.
const prmap = {
plotData: plotData, //An array of 1 or more datasets
lineLabels: lineLabels, //An array of labels for each dataset
colors: myColors, //An array of colors for each dataset
hideLegend: true,
borderWidth: borderWidth,
xLabel: 'Size&', //Label for the x axis, with an & to separate the units
yLabel: 'n&', //Label for the y axis, with an & to separate the units
y2Label: null, //Label for the y2 axis, null if not needed
yAxisL1R2: [], //Array to say which axis each dataset goes on. Blank=Left=1
logX: true, //Is the x-axis in log form?
xTicks: undefined, //We can define a tick function if we're being fancy
logY: true, //Is the y-axis in log form?
yTicks: undefined, //We can define a tick function if we're being fancy
legendPosition: 'top', //Where we want the legend - top, bottom, left, right
xMinMax: [,], //Set min and max, e.g. [-10,100], leave one or both blank for auto
yMinMax: [,], //Set min and max, e.g. [-10,100], leave one or both blank for auto
y2MinMax: [,], //Set min and max, e.g. [-10,100], leave one or both blank for auto
xSigFigs: 'F1', //These are the sig figs for the Tooltip readout. A wide choice!
ySigFigs: 'F0', //F for Fixed, P for Precision, E for exponential
};
//Now we return everything - text boxes, plot and the name of the canvas, which is 'canvas' for a single plot
return {
plots: [prmap],
canvas: ['canvas'],
beta: beta.toFixed(1),
// Peak2: (Peak2*1e6).toFixed(1) + " μm",
// Emitted2: Emitted2.toPrecision(3),
// Flow: Flow.toPrecision(3),
};
}
Universal fragmentation behaviour
It has been known for many years that if you break a brittle object, it shatters into a many small pieces and fewer larger pieces. A log-log plot is a straight line showing that if you have nmin pieces of your smallest (measurable/reasonable) of size dmin then the number, n, of size d depends on β. The published formula is a "proportional to" relationship:
`n~d^-β`
To make it specific, we can normalise it to your input values via:
`n=n_min(d/d_min)^-β`
What had not been known till Villermaux's paper was the reason for this universal behaviour and how β depended on the dimensionality, D of the object. A 1D piece of spaghetti has β=1.3, a 2D object such as a plate or a tube or a flat piece of stone has β=2.4 and a true 3D object such as a sugar cube or a large stone being crushed has β=3.5. All these numbers emerge from two fundamental components making up the new theory.
Although the formula works from stone-age (or chimp-made) stone fragments right through to the bubbles in a breaking ocean wave, there are important exceptions:
- Many liquid breakup phenomena have specific links to viscosity, surface tension, inertia so are deterministic and not stochastic.
- Some materials, such as polymers, will start the cracks that would create smaller pieces, but their relaxation times are fast enough that the small cracks self-heal. A 2D piece of plastic might break up as if it were 1D.
Why this app? Well, the theory is simple, its implementation is simple, but there's nothing like an app to allow people to see for themselves a universal law in action and encouraging others to read a fascinating paper.