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

Min Size
n Min Size
Max Size
Dimension
β
"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.