4. Pump systems#
A pump is used to move fluid through a pipeline.
The flow rate is controlled by a valve.
The pump supplies pressure at various flow rates.
If we divide the pressure by the fluid density and gravity, which are both constant, we get units of length, which we call a head.
So, we can plot head versus flow rate. Here’s an example of a pump curve. (The figure is used with permission.)
We’ll consider the 13.5 inch pump size (top curve).
The flow through the system is related by a mechanical energy balance:
Here, \(z\) is height, \(f\) is the pipe friction factor, \(L\) is the pipe length, \(D\) is the pipe diameter, and \(K\) is a valve coeficient.
We’ll assume the tanks are open to the atmosphere, have no vecocity at the top surface, and are at the same height, so that the left hand side is zero. We’re assuming no other friction losses besides the pipe and the valve. Rearrange this to
The system operates where the operating curve (equation above) and the pump curve in the figure intersect.
That is, the system can operate anywhere on the operating curve defined by the equation above, (that is, any head/flow combination given by that equation), but because the flow is driven by a pump, we are restricted to the points that also lie on the pump curve.
We adjust the intersection point, that is, the operating point of the system, by opening or closing the valve (changing \(K\)). This will effectively pivot the operating curve left or right about the origin.
Consider a pump system with a pipe with the following parameters:
L = 35 m
f = 0.02
D = 0.1
The operating point can be visualizaed by opening/closing a valve (changing \(K\)).
Show code cell source
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
from scipy.optimize import fsolve
import pint; u = pint.UnitRegistry()
from io import BytesIO
import ipywidgets as wg
from IPython.display import display
#------------
Qp = np.array([0.0,20.3,40.5,60.8,80.0,100,121,141,160,180,201,220,240,260,281,301,320,340,361,381,400,420,441,461,480,500,521,541,560,580,600,620,640,660])*u.gal/u.min
hp = np.array([84.8,84.8,84.6,84.6,84.3,83.8,83.5,83.0,82.4,82.2,81.3,80.5,80.0,78.9,78.1,77.3,76.2,74.9,73.5,72.2,70.8,69.0,67.4,65.2,63.3,60.9,58.2,55.5,52.6,49.3,45.8,42.1,37.8,33.2])*u.ft
Qp.ito(u.m**3/u.s)
hp.ito(u.m)
Qp = Qp.magnitude
hp = hp.magnitude
#------------
def operatingcurve(Q, K):
L = 35
D = 0.1
f = 0.02
g = 9.81
v = 4*Q/np.pi/D**2
return f*L*v**2/2/D/g + K*v**2/2/g
#------------
pumpcurve = interp1d(Qp, hp, fill_value='extrapolate')
#------------
plotpic = wg.Image(layout=wg.Layout(width='60%'))
def get_operating_point(K):
def F(Q,K):
return operatingcurve(Q,K)-pumpcurve(Q)
Q = fsolve(F, 0.02, args=(K,))[0]
h = operatingcurve(Q,K)
print(f"Q={Q:.3f} m^3/s,\nh={h:.1f} m")
Qpts = np.linspace(np.min(Qp), np.max(Qp), 100)
plt.plot(Qpts, operatingcurve(Qpts,K))
plt.plot(Qpts, pumpcurve(Qpts))
plt.plot([Q], [h], 'o', markersize=10)
plt.ylim([0,30])
plt.xlabel(r'Q (m$^3$/s)')
plt.ylabel('h (m)')
plotpicdata = BytesIO()
plt.savefig(plotpicdata, format='png')
plt.close()
plotpicdata.seek(0)
plotpic.value = plotpicdata.read()
#------------
userinput = wg.interactive(get_operating_point, K=(0,200,5));
box = wg.VBox([userinput, plotpic])
display(box)