## Fluctuations

### Quick Start

Fluctuation Theory is key to understanding many solubility and solubilization issues. But I've never really understood what all the angled bracket stuff, e.g. 〈δxδx〉, means. Here we use some simple particles to demonstrate the core ideas.

### Credits

The app is based on the patient explanations from Dr Seishi Shimizu at U York, a world-class fluctuation theory expert.

### Fluctuations

_{x-x}

_{y-y}

_{x-y}

```
//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();
};
//Any global variables go here
//Main is hard wired as THE place to start calculating when input changes
//It does no calculations itself, it merely sets them up, sends off variables, gets results and, if necessary, plots them.
function Main() {
saveSettings();
//Send all the inputs as a structured object
//If you need to convert to, say, SI units, do it here!
const inputs = {
F11: sliders.SlideF11.value,
F22: sliders.SlideF22.value,
F12: sliders.SlideF12.value/100,
Perc2: sliders.SlidePerc2.value/100,
}
//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('Results').value = result.Results
//You might have some other stuff to do here, but for most apps that's it for CalcIt!
}
//Here's the app calculation
//The inputs are just the names provided - their order in the curly brackets is unimportant!
//By convention the input values are provided with the correct units within Main
function CalcIt({ F11, F22, F12, Perc2 }) {
let myrng = new Math.seedrandom('hello.');
const dpr = window.devicePixelRatio || 1;
const theCanvas = document.querySelector('canvas')
const ctx = setupCanvas(theCanvas, dpr);
const w = theCanvas.width / dpr, h = theCanvas.height / dpr
const gv = 10.01
const fy=Perc2,fx=1-fy
let GFx = (100.1 - F11) / 2
if (F11 < 10) GFx *= Math.pow(10 - F11, 0.75) //Make the low zone flatter
if (F11 == 0) GFx = 1e99 //And enforce uniformity at 0
let GFy = (100.1 - F22) / 2
if (F22 < 10) GFy *= Math.pow(10 - F11, 0.75) //Make the low zone flatter
if (F22 == 0) GFy = 1e99 //And enforce uniformity at 0
let i = 0, j = 0, k = 0, xv = 0
let pax = [], pay = [], ptot = 0,ptotx=0,ptoty=0
for (i = 0; i <= 10; i++) {
drawLines(ctx, i / gv * w, 0, i / gv * w, h)
drawLines(ctx, 0, i / gv * h, w, i / gv * h)
}
let isOdd=false,xo,yo,px,py
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
isOdd=((i % 2) && !(j % 2)) || (!(i % 2) && (j % 2))
if (isOdd){
xo=1-F12;yo=1+F12
} else {
xo=1+F12,yo=1-F12
}
p = Math.exp(-(((i - 4-F12/0.5) * (i - 4-F12/0.5) + (j - 4) * (j - 4))) / GFx)
px=p * fx*xo*10
pax.push(px)
ptotx += px
p = Math.exp(-(((i - 4+F12/0.5) * (i - 4+F12/0.5) + (j - 4) * (j - 4))) / GFy)
py=p * fy*yo*10
pay.push(py)
ptoty += py
}
}
//Scale to 1000 particles
if (ptotx > 0) ptotx=fx*1000/(ptotx)
if (ptoty > 0) ptoty=fy*1000/(ptoty)
let pc = 0, Nx,Ny, xdN2, ydN2, xydN2, xdNAv = 0, ydNAv = 0, xydNAv = 0
ctx.font = "20px Arial"
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
Nx = Math.floor(ptotx * pax[pc])
xdN2 = Math.pow(Nx - 10*fx, 2)
xdNAv += xdN2
for (k = 0; k < Nx; k++) {
drawDots(ctx, "orange", 4, i / 10 * w + w / 10 * myrng(), j / 10 * h + h / 10 * myrng())
}
Ny = Math.floor(ptoty * pay[pc])
ydN2 = Math.pow(Ny - 10*fy, 2)
ydNAv += ydN2
for (k = 0; k < Ny; k++) {
drawDots(ctx, "skyblue", 4, i / 10 * w + w / 10 * myrng(), j / 10 * h + h / 10 * myrng())
}
xydN2=(Nx-10*fx)*(Ny-10*fy)
xydNAv+=xydN2
ctx.fillStyle = "black"
// ctx.fillText(Ni.toFixed(0), i / 10 * w + w / 100, j / 10 * h + 2 * h / 50)
// ctx.fillText(xdN2.toFixed(0), i / 10 * w + w / 100, j / 10 * h + 4 * h / 50)
pc++
}
}
xv = (xdNAv / 100)
yv = (ydNAv / 100)
xyv = (xydNAv / 100)
return {
Results: "<δxδx>=" +xv.toPrecision(4) + ", <δyδy>=" +yv.toPrecision(4)+", <δxδy>=" +xyv.toPrecision(4),
};
}
function drawDots(ctx, col, lw, xv, yv) {
ctx.fillStyle = col;
ctx.beginPath();
ctx.arc(xv, yv, lw, 0, 2 * Math.PI);
ctx.fill();
}
function drawLines(ctx, xs, ys, xe, ye) {
ctx.strokeStyle = "black";
ctx.beginPath();
ctx.moveTo(xs, ys);
ctx.lineTo(xe, ye);
ctx.stroke();
}
function setupCanvas(canvas, dpr) {
// Get the device pixel ratio, falling back to 1.
var rect = canvas.getBoundingClientRect();
// Give the canvas pixel dimensions of their CSS
// size * the device pixel ratio.
canvas.width = rect.width * dpr;
canvas.height = rect.height * dpr;
var ctx = canvas.getContext('2d');
// Scale all drawing operations by the dpr, so you
// don't have to worry about the difference.
ctx.scale(dpr, dpr);
return ctx;
}
```

Fluctuation theory is a powerful method to see what is going on in a solution or at an interface. It can be expressed in some numbers that are simple to describe and calculate but which are hard to grasp intuitively. Here we can play with all the key influences of particles on each other, and see how they translate into the language of N, δ and the <brackets> that simply mean "Take the average".

Start with the default values of all 0. We have a 10x10 grid and in each cell we have 10 particles at random. Looking at the big picture, we have 1000 particles in 100 grid positions so there's an average of 10 per grid. We call that average <N_{x}>. In each cell we have an actual count of N_{x} and we calculate δ_{x}=N_{x}-<N_{x}>. We then, and this at first seems strange, multiply it by itself to get δ_{x}δ_{x} values in each cell. We sum all these local δ_{x}δ_{x} values, divide by 100 and get <δ_{x}δ_{x}>, their average.

With the default values this average = 0. There are no fluctuations from the average. Now slide the Fluctuation_{x-x} slider. At first nothing obvious happens to the particles, but you see <δ_{x}δ_{x}> slowly increase. The calculation easily picks up that some cells have 1 fewer particle, so <δ_{x}δ_{x}>=1 and some cells have 1 extra particle, giving <δ_{x}δ_{x}>=1. As you carry on sliding, some cells lose 2 or 3 particles, so now their contribution to the averge is 4 or 9, just as with those cells that gain 2 or 3. So <δ_{x}δ_{x}> is capturing small but meaningful fluctuations from the mean. As you slide to the maximum value the fluctuation becomes obvious, and at 100 all the particles are in the central cell.

If you set %2 to 100 and slide Fluctuation_{y-y}, then you have the same scenario as with x, just with blue particles rather than orange ones. Now set %2 to 50, so you have equal x and y particles. Now things get more complicated as they depend on both Fluctuation_{x-x} and Fluctuation_{y-y}. And you also find you have a value that captures the fluctuations around the x & y means,<δ_{x}δ_{y}>

So far, we've assumed that x and y don't have a special dislike for each other. But if you now slide Fluctuation_{x-y} they become more and more separated. The simulation ceases to be rigorous, but the general idea is sound. The opposite case of x and y being attracted is not covered, but you can work out then general principle.

### The symbols we use

Simplifying the nomenclature somewhat, have x fluctuating around a mean, with, as a default, everything symmetrical, the mean of x, 〈x〉 = 0, using the angled brackets. As we know from statistics, we can capture how much variation there is about the mean via the Variance, which can be defined in two ways that are arithmetically equivalent. The first way is intellectually clearer, the second way is computationally simpler. Confusingly, we see different nomenclatures for the variance, each included here

`"〈"δx^2"〉" = "〈"δxδx"〉" = (σ^2)_x = Var(x) = (x-"〈"x"〉")(x-"〈"x"〉")`

The curious δx terms are simply δx=x-〈x〉, i.e. δx is the difference between x at that moment in time (or position in space - the two are equivalent) and the mean 〈x〉, the equation is just restating itself. The other way to calculate it (just multiply to get x²-2x〈x〉+〈x〉² = x²-〈x〉²) is:

`"〈"δx^2"〉" = "〈"δxδx"〉" = (σ^2)_x = Var(x) = "〈"x^2"〉"-"〈"x"〉""〈"x"〉"`

We can do the same things for y. But what's of interest is the Covariance, how X and Y are interrelated.

`"〈"δxδy"〉" = (σ)_(xy) = Covar(x,y) = (x-"〈"x"〉")(y-"〈"y"〉")`

and, of course, the equivalent:

`"〈"δxδy"〉" = (σ)_(xy) = Covar(x,y) = "〈"xy"〉"-"〈"x"〉""〈"y"〉"`

*After all this we need one more fact. What everyone calls Variance and Covariance, statistical thermodynamicists call Fluctuation.* I suppose they could have called it all Covariance, but although it's respectable to talk about X,X covariance, it's a bit odd. So the single term "fluctuation" ended up as doing the job.

### Solubility/solubilization theory

We can now look at the definition of a Kirkwood-Buff integral, a number that describes how much or how little something likes itself compared to the average with the mysterious nomenclature removed. Here we see G_{XX} and G_{XY}, how much X likes itself compared to the average and how much X and Y (dis)like each other. These are expressed in terms of N, the number of moles of each species present. For simplicity some pesky volume and Kroneker delta terms are omitted:

`G_(XX) ~ ("〈"δ_Xδ_X"〉")/("〈"N_X"〉""〈"N_X"〉"` and `G_(XY) ~ ("〈"δ_Xδ_Y"〉")/("〈"N_X"〉""〈"N_Y"〉"`

Translated into normal language this means that the size of the effect is the (co)variance normalized by the means. The bigger the absolute (co)variance, the larger the G_{ij} value. Or, to put it more correctly, if we find a large positive G_{ij} that means i and j prefer to be together more than the average, and a large negative value means they prefer to keep apart.