RI & Particle Size
Quick Start
With a modern digital refractometer it is possible to measure not just the volume fraction, φ, of particles but changes in particle size, d, based on the change in RI at constant φ. Although the equation has been known for years, and is related to the one used in Mie Scattering, it was brought into practical use1 by Dr Mansur S. Mohammadi at Unilever who kindly helped in the development of this app.
RI & Particle Size
//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 = {
nm: sliders.Slidenm.value,
np: sliders.Slidenp.value,
lambda: sliders.Slidelambda.value,
d: sliders.Slided.value*1000, //μm to nm
dmax: sliders.Slidedmax.value, //keep in μm
phi: sliders.Slidephi.value,
AR: sliders.SlideAR.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('dS').value = result.dS;
//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({ nm, np,lambda, d,dmax,phi, AR }) {
let nd=[], nphi=[]
const sr1=Math.sqrt(AR*AR-1)
const dS=AR>1?d*Math.sqrt((2*AR*Math.log(AR+sr1))/(sr1+AR*AR*Math.atan(sr1))):d
let tmp = 2 * Math.PI * (np - nm) /lambda
let p = tmp*0.01, n = 1
for (i = 0.01; i <= dmax; i+=0.01) {
p = i * tmp*1000
n =nm+phi*(np-nm) *(3*Math.sin(p)/p**3-3*Math.cos(p)/p**2)
nd.push({x:i, y:n})
}
p = 2 * Math.PI * (np - nm) *d/lambda
for (i = 0; i <= 0.7; i+=0.01) {
n =nm+i*(np-nm) *(3*Math.sin(p)/p**3-3*Math.cos(p)/p**2)
nphi.push({x:i, y:n})
}
const plotData = [nd]
const plotData1 = [nphi]
const lineLabels = ["n dependence on d at φ = "+phi]
const lineLabels1 = ["n dependence on φ at d = "+d/1000+"μm"]
const myColors = ["blue"]
const myColors1 = ["orange"]
const borderWidth = [2]
//Now set up all the graphing data detail by detail.
const prmap = {
plotData: plotData, //An array of 1 or more datasets
fontSize:20,
lineLabels: lineLabels, //An array of labels for each dataset
colors: myColors, //An array of colors for each dataset
hideLegend: false,
borderWidth: borderWidth,
xLabel: 'd&μm', //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: false, //Is the x-axis in log form?
xTicks: undefined, //We can define a tick function if we're being fancy
logY: false, //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: 'F2', //These are the sig figs for the Tooltip readout. A wide choice!
ySigFigs: 'P5', //F for Fixed, P for Precision, E for exponential
};
const prmap1 = {
plotData: plotData1, //An array of 1 or more datasets
lineLabels: lineLabels1, //An array of labels for each dataset
colors: myColors1, //An array of colors for each dataset
hideLegend: false,
borderWidth: borderWidth,
xLabel: 'φ&', //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: false, //Is the x-axis in log form?
xTicks: undefined, //We can define a tick function if we're being fancy
logY: false, //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: 'F2', //These are the sig figs for the Tooltip readout. A wide choice!
ySigFigs: 'P5', //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, prmap1],
dS: (dS/1000).toFixed(2),
canvas: ['canvas', 'canvas1'],
};
}
The refractive index, n, of a dispersion measured at wavelength λ, depends on the refractive index of the particle, np compared to that of the medium nm and on the volume fraction of particles, φ.
We first calculate a value, p, depending on the refractive indice ratio between the particles and the medium and on the ratio of particle size, d, to wavelength:
`p=2πd(n_p-n_m)/λ`
Then the refractive index, n, is given by:
`n=n_m+φ(n_p-n_m)((3sinp)/p^3-(3cosp)/p^2)`
Now we can plot the refractive index at our refractometers's λ with varying particle size d at a fixed φ, or at a fixed d with varying φ. The dmax slider lets you set the range of interest. The oscillations you see at higher d values have been experimentally validated, with larger differences in refractive index producing more oscillations.
Although the theory is for an idealised particle size d, it turns out that the measured value is d4,3, the standard volume-weighted average.
Aspect ratio
The formula above applies to spherical particles. Dr Zivorad Lazic kindly pointed out that for non-spherical particles with an aspect ratio `r="Length"/"Width"`, the diameter that is relevant to this RI effect, let's call it da, is different from the diameter you'd measure from Stokes sedimentation, dS. The Stokes sedimentation app includes a correction for aspect ratio based on a famous paper by Jennings and Parslow2. That same paper has an equation to convert between dS and da:
`d_S/d_a={(2rln[r+sqrt(r^2-1)])/(sqrt(r^2-1)+r^2arctan(sqrt(r^2-1)))}^0.5`
So if you measure your particles via this technique or conventional light scattering you can now predict the diameter if measured via a sedimentation technique. Or to put it another way, be careful when you quote diameters of non-spherical particles!
Layman's Guide
Dr Mohammadi has kindly provided a version of a guide from 1993 on the details of measuring refractive index (as well as other techniques). Click the link to download his Measurement Techniques.pdf
Mansur S. Mohammadi, Colloidal Refractometry: The Art of Microstructure Characterization, in Particle Sizing and Characterization, ACS Publications, 2004.
B. R. Jennings and K. Parslow, Particle Size Measurement: The Equivalent Spherical Diameter, Proc. Royal Soc. London. Series A, Mathematical and Physical Sciences, 419, No. 1856. 1988, 137-149