What you can do
You can price a grind spec before anyone mills a powder. Hold the total loading fixed, change only how that loading is split between particle sizes, and measure what it does to the space left over. The pore size that results is a design output, not something you have to accept from the powder you happen to have.
- fillerConfigs takes more than one entry, so a bimodal blend is one array with two radii and two volume fractions.
- The generator hits the total loading you ask for, which means the blends stay comparable.
- POST /api/v1/chord-length returns the pore-phase chord distribution along each axis, which is the direct measure of how wide the channels are.
- POST /api/v1/metrics returns specific surface area and tortuosity from the same stored structure.
- Repeating a blend on several seeds tells you how much of a difference is the blend and how much is one lucky packing.
Why it matters
Loading is what gets written on a spec sheet. Particle size distribution usually does not, or it appears as a single D50. Two powders can meet the same 45 % target and leave behind completely different pore space.
Adding fines to raise packed density is a common move in electrode and ceramic work. The fines also sit in the gaps between the coarse particles, which is exactly where anything has to travel. Being able to see that trade as a number, before committing to a powder, is the useful part.
Four blends, one loading
Everything is held fixed except the size split. The grid is 64³ at 1 µm per voxel, the target is 45 % by volume, particles may overlap by 15 %, and all particles carry the same material id.
- Coarse only — one population of 4 µm-radius spheres at 45 %.
- Bimodal 75:25 — 4 µm spheres at 33.75 % plus 2 µm spheres at 11.25 %.
- Bimodal 50:50 — 4 µm spheres at 22.5 % plus 2 µm spheres at 22.5 %.
- Fine only — one population of 2 µm-radius spheres at 45 %.

Each blend was built on four seeds, for sixteen structures in all. The generator hit the target every time: solid fraction came back between 45.00 % and 45.09 %. Nothing below can be explained by one blend carrying more material than another.
The pore size moves, and it moves cleanly
Mean pore chord length falls by 41 % from the coarse blend to the fine one, and the four blends never overlap.
| Blend | Solid | Pore chord, z (µm) | Specific surface (µm⁻¹) | Tortuosity, z |
|---|---|---|---|---|
| Coarse only | 45.04 % | 7.24 (7.11–7.38) | 0.492 | 1.004 |
| Bimodal 75:25 | 45.03 % | 6.00 (5.97–6.06) | 0.595 | 1.032 |
| Bimodal 50:50 | 45.05 % | 5.18 (5.10–5.23) | 0.691 | 1.056 |
| Fine only | 45.00 % | 4.24 (4.19–4.32) | 0.856 | 1.075 |
Each figure is the mean of four seeds, with the seed range in brackets for the chord length. The widest spread any blend showed across its four seeds was 0.27 µm. The smallest gap between two neighbouring blends was 0.82 µm, three times larger. The ladder is the blend, not the luck of one packing.
Specific surface area separates the blends even harder. It rises from 0.492 to 0.856 per µm while the four seeds of a blend agree to within 0.005. That is the other half of the same trade: the fines that narrow the channels are also the fines that give you more interface to react at.
Tortuosity along z climbs from 1.004 to 1.075. The path through the pore space really does get more crooked, but the effect is small and adjacent blends overlap. Only the two ends of the range are cleanly apart.
Permeability did not follow
Narrower channels did not show up as lower permeability. The obvious next step is to read a transport penalty off the pore size, and on these structures that reading is not available.
| Blend | Permeability, z, four seeds (µm²) |
|---|---|
| Coarse only | 0.245, 0.258, 0.275, 0.293 |
| Bimodal 75:25 | 0.263, 0.273, 0.283, 0.285 |
| Bimodal 50:50 | 0.266, 0.267, 0.268, 0.276 |
| Fine only | 0.262, 0.277, 0.291, 0.294 |
The four blend means sit within 0.013 µm² of each other, and they are not in order. Meanwhile the coarse-only blend alone spans 0.048 µm² across its own four seeds. The scatter within a blend is nearly four times the difference between blends, so there is no ranking here to report.
This is worth knowing in its own right. Pore size is often used as a stand-in for how easily something flows, and here it moved by 41 % while the flow number stayed put. At this porosity the blends are not separable on permeability without far more replicates than four.
Running it on your own recipe
Generate once per blend and seed, store the structure, then send the id to each measurement. A bimodal blend is two entries in fillerConfigs.
POST /api/v1/generate -> structureId
{
"recipe": {
"generatorType": "particlePacking",
"grid": { "nx": 64, "ny": 64, "nz": 64, "voxelSizeUm": 1 },
"fillerConfigs": [
{ "type": "sphere", "radius": 4, "volumeFraction": 22.5, "materialId": 1 },
{ "type": "sphere", "radius": 2, "volumeFraction": 22.5, "materialId": 1 }
],
"volumeFraction": 45,
"overlapPercent": 15,
"randomness": { "seed": 20260912 }
},
"storeStructure": true
}
POST /api/v1/chord-length
{ "structureId": "<id>" }
-> chordLength.phases.pore.z.meanLengthUm
One detail costs people time. The per-entry volumeFraction values have to be written out by hand so that they add up to the total. Helpers that set a loading on an existing recipe tend to split it evenly across the entries, which silently turns every blend you asked for into 50:50.
The whole study is cheap. Sixteen structures went through metrics, chord length, percolation path, permeability and conductivity. That came to 102 requests and 44 seconds of API time in total. A generate call took between 312 and 1,671 ms, a chord-length call between 185 and 368 ms.
Run the seed replicates from the start. Two structures per blend would have been enough to see the chord ladder, and would also have been enough to invent a permeability ranking that four seeds do not support.
What this does not settle
This is one generator, one box size, one loading, one size ratio and four seeds. A 2:1 radius ratio on a 1 µm grid means the fine particles are only four voxels across, so a wider ratio needs a finer grid before the small population is resolved at all.
The permeability numbers come from the pore-network method, which reduces the pore space to pores and throats rather than solving on all 262,144 voxels. Its seed scatter here is large enough to hide the blend effect. That does not prove the blend effect is zero, only that four seeds at 64³ cannot find it.