Flow Curves
Quick Start
When we think about flow curves we default to viscosity versus shear rate. That's the default for the classic Shear-Viscosity app. But it turns out that a flow curve based on shear stress rather than shear rate can be much more informative, especially for coating phenomena at low stresses.
Flow Curves
//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 = {
V0: sliders.SlideV0.value,
Vinf: sliders.SlideVinf.value,
alpha: sliders.Slidealpha.value,
n: sliders.Sliden.value,
t0: sliders.Slidet0.value,
K: sliders.SlideK.value,
HBn: sliders.SlideHBn.value,
SRmax: sliders.SlideSRmax.value,
Cross: document.getElementById('Cross').checked,
HB: document.getElementById('HB').checked,
Log: document.getElementById('Log').checked,
Stress: document.getElementById('Stress').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('ty').value = result.ty;
//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({V0, Vinf, alpha, n, t0,K,HBn, SRmax, Cross, HB, Log, Stress }) {
let VPts=[], SPts=[],i=0.1 //0.318
while (i <= 100) {
sr = i * i
if (sr>SRmax) break
if (Cross){
v = Vinf + (V0 - Vinf) / (1 + Math.pow(alpha * sr, n))
sstress=v*sr
} else
{
sstress=t0+K*Math.pow(sr,HBn)
v=sstress/sr
}
if (!Stress){
VPts.push({x:sr,y:v})
SPts.push({x:sstress,y:v})
} else {
VPts.push({x:sr,y:sstress})
SPts.push({x:sstress,y:sstress})
}
if (i < 10) {
i += 0.1
} else {
i += 1
}
}
const plotData = [VPts]
const plotData1 = [SPts]
const yLabel=! Stress?'Viscosity&Pa.s':"Shear Stress&Pa"
//Now set up all the graphing data detail by detail.
const prmap = {
plotData: plotData, //An array of 1 or more datasets
lineLabels: "Viscosity", //An array of labels for each dataset
colors: ["blue"], //An array of colors for each dataset
hideLegend: true,
borderWidth: 2,
xLabel: 'Shear Rate γ̇ &/s', //Label for the x axis, with an & to separate the units
yLabel: yLabel, //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: Log, //Is the x-axis in log form?
xTicks: function(value, index, ticks) {if (!Log) {return value} else {if (value.toPrecision(2).includes("1") || value.toPrecision(2).includes("4")) {if (value>=1) {return value.toFixed(0)} else {return value.toPrecision(1)} } else {return ""}}; }, //We can define a tick function if we're being fancy
logY: Log, //Is the y-axis in log form?
yTicks: function(value, index, ticks) {if (!Log) {return value} else {if (value.toPrecision(2).includes("1") || value.toPrecision(2).includes("4")) {if (value>=1) {return value.toFixed(0)} else {return value.toPrecision(1)} } else {return ""}}; }, //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: 'P3', //These are the sig figs for the Tooltip readout. A wide choice!
ySigFigs: 'P3', //F for Fixed, P for Precision, E for exponential
};
const prmap1 = {
plotData: plotData1, //An array of 1 or more datasets
lineLabels: "Viscosity", //An array of labels for each dataset
colors: ["orange"], //An array of colors for each dataset
hideLegend: true,
borderWidth: 2,
xLabel: 'Shear Stress&Pa', //Label for the x axis, with an & to separate the units
yLabel: yLabel, //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: Log, //Is the x-axis in log form?
xTicks: function(value, index, ticks) {if (!Log) {return value} else {if (value.toPrecision(2).includes("1") || value.toPrecision(2).includes("4")) {if (value>=1) {return value.toFixed(0)} else {return value.toPrecision(1)} } else {return ""}}; },
logY: Log, //Is the y-axis in log form?
yTicks: function(value, index, ticks) {if (!Log) {return value} else {if (value.toPrecision(2).includes("1") || value.toPrecision(2).includes("4")) {if (value>=1) {return value.toFixed(0)} else {return value.toPrecision(1)} } else {return ""}}; },
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: 'P3', //These are the sig figs for the Tooltip readout. A wide choice!
ySigFigs: 'P3', //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'],
};
}
Although flow curves can be described by many different fitting formulae, the two most popular are the Cross model and the Herschel-Bulkley model (which reduces to a Power Law model). They each have their uses for specific applications. Feel free to choose whichever you prefer.
Whichever version you choose, the plots themselves can be:
- Viscosity versus Shear rate
- Viscosity versus Shear stress
- Shear stress versus Shear rate
- Logarithmic or Linear
The merits of shear stress
Very often the rheological effects are obviously controlled by shear rate. So the standard flow curve is fine. But especially for effects like levelling or sag in paints and coatings, the effect is dominated by the available shear stress. For example, a thick layer of paint might have a shear stress of 1 to 10 Pa. If that stress is beyond the viscosity of the paint, the paint will level (good) or sag (bad). The shear rate of levelling or sagging is an effect, while the shear stress is a cause.
Attempts to correlate these effects with viscosities at controlled shear rates are usually a failure. Correlations with viscosities at controlled shear stresses are generally good. It's not a coincidence that there is also a good correlation with G' (or tanδ values, G''/G') and these effects - as long as the oscillatory measure is made at low strain amplitudes (e.g. 0.001), and shortly after a strong pre-shear to mimic the application process.
Cross model
`η = η_"inf"+(η_0-η_"inf")/(1+(α.γ̇)^n)`
where ηinf is the viscosity at (essentially) infinite shear, η0 is the viscosity at zero shear and α and n are fitting constants.
Herschel-Bulkley & Power Law
Here we calculate the shear stress τ which might have a yield stress τ0 ...
`τ = τ_0+Kγ̇^n`
... and then calculate viscosity as stress/shear rate.
`η = (τ_0+Kγ̇^n)/"γ̇"`
If we want a pure Power Law fluid then τ0 is set to 0 so that `η=Kγ̇^(n-1)`. The n value is the power and K is the "consistency factor" with the strange units of (Pa.sn). For paint sag, a correlation with a simple power law turns out to be better than with fits involving the hard-to-pin down yield stress.