Foam Mie

Quick Start

Shine white light through some foam samples and you see light with a different colour thanks to scattering. Because Rayleigh scattering is to do with dilute, individual particles, the scattering is best described via Mie theory.

Credits

This app was developed for the Science of (PU) Foam with Dr Grażyna Mitchener.

Foam Mie

nsolid
λ nm
φ nm
IR
//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 = {
        n: sliders.Sliden.value,
        lambda: sliders.Slidelambda.value, //No need to convert to nm
        phi: sliders.Slidephi.value/2, //Because we use their ratio
        IR: document.getElementById('IR').checked,
    };

    //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('phiphi').value = result.phiphi; 
    //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({ n, lambda, phi, IR }) {
    let Rad=[], L=[]
    const nm = 1
    if (IR) {
        sliders.Slidelambda._input.max=60000
        sliders.Slidephi._input.max=60000
        // sliders.Slidelambda._max=60000
        // sliders.Slidephi._max=60000
        // sliders.Slidelambda._logMax=60000
        // sliders.Slidephi._logMax=60000
        // sliders.Slidelambda._result=60000
        // sliders.Slidephi._result=60000
   } else {
        sliders.Slidelambda._input.max=2000
        sliders.Slidephi._input.max=2000
    }
    let tmp = 4 * Math.PI * (n / nm - 1) / lambda
    let p = 0, Q = 0
    const LRange= IR?60000:2000
    const PRange= IR?60000:2000
    for (i = 1; i <= PRange; i++) {
        p = i * tmp/2
        Q = 2 - 4 / p * Math.sin(p) + 4 / (p * p) * (1 - Math.cos(p))
        Rad.push({x:i, y:Q})
    }
    tmp = 4 * Math.PI * (n / nm - 1) 
    for (i = 400; i <= LRange; i++) {
        p =tmp*phi/i
        Q = 2 - 4 / p * Math.sin(p) + 4 / (p * p) * (1 - Math.cos(p))
        L.push({x:i, y:Q})
    }


    const plotData = [Rad]
    const plotData1 = [L]
    const lineLabels = ["φ dependence at chosen wavelength λ"]
    const lineLabels1 = ["λ dependence at chosen cell size φ"]
    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: 'φ&nm', //Label for the x axis, with an & to separate the units
        yLabel: 'Scattering& ', //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: 'F0', //These are the sig figs for the Tooltip readout. A wide choice!
        ySigFigs: 'F2', //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: 'λ&nm', //Label for the x axis, with an & to separate the units
        yLabel: 'Scattering& ', //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: [0,], //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: 'F0', //These are the sig figs for the Tooltip readout. A wide choice!
        ySigFigs: 'F2', //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],
        canvas: ['canvas', 'canvas1'],
    };
}
            

The scattering from features of typical dimension φ at wavelength λ can be approximated by Mie theory. The scattering depends on the refractive index, nsolid of the cell material (in this case foam cells) compared to the air (or other gas) with n = 1.

Although Mie theory is complex, the van den Hulst approximation does an adequate job. We first calculate a value, p, depending on the refractive indices and the ratio of cell size, φ, to wavelenght λ:

`p=4π(n/n_"solid"-1)φ/(2λ)`

Then the scattering, Q, is given by:

`Q=2-(4/p)sin(p)+(4/p^2)(1-cos(p))`

Now we can plot the data at a fixed λ with varying cell size φ, or at a fixed φ with varying λ.

The plots may throw light on how different wavelengths of visible and IR light interact with the foams, for better or worse.