This notebook contains material from chemeng316_fluids; content is available on Github.
CoolProp
¶For many chemical applications we need more complex models for fluid properties, but for simple calculations that involve a single fluid we can use molecular models of pure substances.
I use CoolProp because it is a free port of many substances in the NIST RefProp database. CoolProp: equations of state and transport properties for 122 components.
There are two possible ways to use this:
I always need to use units, so I will go ahead and get this loaded.
try:
import pint
except:
!pip install pint
import pint
finally:
ur = pint.UnitRegistry()
The try
-except
helps to keep from installing something if it is already available.
try:
from pyfluids import Fluid, FluidsList, Input
except:
!pip install pyfluids
from pyfluids import Fluid, FluidsList, Input
T_degF = ur.Quantity(60, ur.degF);
T_K = T_degF.to(ur.degK);
T_C = T_K.to(ur.degC);
Tin = T_C.magnitude;
thisWater = Fluid(FluidsList.Water).with_state(
Input.temperature(Tin),Input.quality(0)
)
rho = thisWater.density * ur.kilogram / ur.meter ** 3;
f"{rho:~P}" # pint gives a nice way to print "pretty" [~P] units
'998.9707010071485 kg/m³'
try:
import CoolProp.CoolProp as CP
except:
!pip install CoolProp
import CoolProp.CoolProp as CP
rho_kgPerM3 = CP.PropsSI("D","T",T_K.magnitude,"Q",0.0,"Water") * ur.kilogram / ur.meter **3;
f"{rho:~P}"
'998.9707010071485 kg/m³'
from CoolProp.CoolProp import PhaseSI, PropsSI
rho_kgPerM3 = PropsSI("D","T",T_K.magnitude,"Q",0.0,"Water") * ur.kilogram / ur.meter **3;
f"{rho:~P}"
'998.9707010071485 kg/m³'
Water at 60 $^\circ$F is to be pumped to the top of a mountain through a 6-inch Schedule 120 pipe at an average velocity of 12 ft/s. The pipe discharges into atmospheric at 3000 ft above the supply reservoir and the pipe itself is 4,500 feet long. Assume a pump efficiency of 70\% and a cost of energy at $0.04/kw-hr, and determine the hourly cost for pumping the water.
For this problem we need the properties of water. This example uses CoolProp
. I first set up the given parameters and use pint
for engineering units.
try:
import pint
except:
!pip install pint
import pint
finally:
ur = pint.UnitRegistry()
Di = 139.76 / 1000 * ur.m; # m
T = ur.Quantity(60.0, ur.degF).to(ur.degK);
Vavg = 12 * ur.feet / ur.s;
Vavg.ito(ur.m/ur.s); # convert "in-place" to SI units
H = ur.Quantity(3000, ur.feet).to(ur.m); # Reservoir pump height
L = ur.Quantity(4500, ur.feet).to(ur.m); # Length of Pipe
eta = 0.7; # pump efficiency
eCost = 0.04 / (1000 * ur.watt_hour);
I'm going to use the PropsSI
interface for CoolProp
.
rho_kgPerM3 = PropsSI("D","T",T_K.magnitude,"Q",0.0,"Water") * ur.kilogram / ur.meter **3;
mu = PropsSI("V","T",T_K.magnitude,"Q",0.0,"Water") * ur.Pa * ur.s ;
{f"{rho:~P}", f"{mu:~P}"}
{'0.001121084308893493 Pa·s', '998.9707010071485 kg/m³'}
I'll go ahead and finish out this example to show all the features of working through a complete problem.
I need some features from numPy: the fundametal package for scientific computing with Python. Specifically, I need the definition of $\pi$.
import numpy as np
area_crossSection = np.pi * Di ** 2 / 4;
Q_flowrate = Vavg * area_crossSection;
mDot = rho_kgPerM3 * Q_flowrate;
{f"{area_crossSection:~P}",f"{Q_flowrate:~P}",f"{mDot}"}
{'0.015341070484943889 m²', '0.056111499405730764 m³/s', '56.05374389590506 kilogram / second'}
Re = rho_kgPerM3 * Di * Vavg / mu;
print(Re)
455505.44997628545 kilogram / meter / pascal / second ** 2
Re.ito(ur.meter/ur.meter)
print(Re)
455505.44997628545 dimensionless
Re.magnitude
455505.44997628545
The friction factor, as it is known, is so ubiquitous that you can find a very nice Wikipedia page that even lists an entire host of approximate equations to estimate the friction factor.
I'm going to compute this with the Haaland equation rather than reading off the chart.
$$ \frac{1}{\sqrt{f}} = -1.8 \log \left[\left(\frac{\epsilon/D}{3.7}\right)^{1.11} + \frac{6.9}{\textrm{Re}}\right] $$k = 0.045 * ur.millimeter;
kByD = k.to(ur.meter) / Di;
Cff = -1.8 * np.log10(6.9/Re + (kByD/3.7)**1.11)
f = (1/Cff)**2;
print(f)
0.016425778363634604 dimensionless
Compare to the Swamee-Jain Equation
$$ f = \frac{0.25}{\left[\log\left(\frac{\epsilon/D}{3.7} + \frac{5.74}{\textrm{Re}^{6.9}}\right)\right]^2} $$f_sj = 0.25 / (np.log10(kByD/3.7 + 5.74/Re**6.9))**2;
print(f)
0.016425778363634604 dimensionless
IMPORTANT Notice how close the two values are in the above results. These are both more accurate than reading values off a chart manually.
Notice: in the equations above, the friction factor, $f$, is defined following Darcy-Weisbach so that the $\Delta P$ calculation has $0.5\rho V^2$ as the momentum reference.
So, to calculate the pressure drop over the length of pipe I need to use:
$$ \frac{\Delta P}{L} = \frac{f}{D}\left(\frac{1}{2}\rho V_{avg}^2\right) $$delPbyL = (f / Di) * (0.5 * rho_kgPerM3 * Vavg ** 2)
delPbyL.ito(ur.Pa / ur.meter)
print(delPbyL)
785.3409423476201 pascal / meter
The pressure required due to gravity must also be included.
g = ur.Quantity(9.8, ur.meter / ur.s ** 2);
delP_lift = rho_kgPerM3 * g * H;
print(delP_lift.to(ur.Pa))
8951896.328209177 pascal
delP_total = delPbyL * L + delP_lift;
print(delP_total)
10029069.964733172 pascal
This is $$ Power = \Delta P \dot{Q} = \frac{\Delta P}{\rho}\dot{m}$$
Power_required = delP_total * Q_flowrate;
print(Power_required.to(ur.kilowatt))
562.7461533661577 kilowatt
Take the efficiency into account.
costToPump = eCost * ( Power_required ) / eta;
print(costToPump.to(1/ur.hour))
32.156923049494736 / hour
The cost to pump is $32.15 per hour
.