Note
Go to the end to download the full example code or to run this example in your browser via JupyterLite.
Žukauskas’s tube banks in crossflow (1972)#
Boilers, air heaters and the cores of most shell-and-tube exchangers are
banks of tubes in crossflow. The first rows see the free stream; deeper
rows sit in the wakes of the ones ahead, whose turbulence raises their heat
transfer. Algirdas Žukauskas, at the Lithuanian Academy of Sciences in
Kaunas, gathered decades of his laboratory’s measurements on aligned and
staggered banks into one form, \(\bar{Nu} = C_2 C Re_{max}^m Pr^{0.36}
(Pr/Pr_s)^{1/4}\), with constants for each layout and Reynolds range and a
correction \(C_2\) for banks of fewer than 20 rows
(zukauskas_nusselt(), with
tube_bank_max_velocity()). This example
sizes an air heater with it and compares the two layouts.
import matplotlib.pyplot as plt
import numpy as np
from engineeringkit.heat_transfer import churchill_bernstein_nusselt, tube_bank_max_velocity, zukauskas_nusselt
An air heater#
Air at 15 °C and 6 m/s crosses a staggered bank of 7 rows of 16.4 mm tubes (\(S_T = 31.3\) mm, \(S_L = 34.3\) mm) held at 70 °C by condensing steam (Incropera et al., Example 7.7). Air properties at the mean temperature; \(Pr_s\) at the surface.
D, ST, SL, V, rows = 0.0164, 0.0313, 0.0343, 6.0, 7
nu, k, Pr, Pr_s = 14.82e-6, 0.0253, 0.710, 0.701
V_max = tube_bank_max_velocity(V, D, ST, SL, "staggered")
Re = V_max * D / nu
Nu = zukauskas_nusselt(Re, Pr, ST, SL, "staggered", rows=rows, Pr_s=Pr_s)
h = Nu * k / D
print(f"V_max = {V_max:.2f} m/s, Re = {Re:.0f}, Nu = {Nu:.1f}, h = {h:.1f} W/(m² K)")
# The book rounds C = 0.35 (S_T/S_L)^0.2 to 0.34 and finds Nu = 87.9 and h = 135.6 W/(m² K).
assert abs(h / 135.6 - 1) < 0.02
V_max = 12.60 m/s, Re = 13948, Nu = 88.8, h = 137.0 W/(m² K)
Air temperature through the bank#
With \(N_T\) tubes per row, the outlet temperature follows from an energy balance on a log-mean temperature difference, \((T_s - T_o)/(T_s - T_i) = \exp[-\pi DNh/(\rho VN_TS_Tc_p)]\).
rho, cp, Ts, Ti, NT = 1.217, 1007.0, 70.0, 15.0, 8
N = rows * NT
To = Ts - (Ts - Ti) * np.exp(-np.pi * D * N * h / (rho * V * NT * ST * cp))
dT_lm = ((Ts - Ti) - (Ts - To)) / np.log((Ts - Ti) / (Ts - To))
q = N * h * np.pi * D * dT_lm
print(f"outlet {To:.1f} °C, heat rate {q / 1000:.1f} kW per metre of tube length")
assert np.isclose(q, rho * V * NT * ST * cp * (To - Ti), rtol=1e-12)
outlet 25.6 °C, heat rate 19.6 kW per metre of tube length
Deeper banks and the two layouts#
Each extra row helps less, and beyond 20 the average no longer changes. Both layouts transfer about twice as much as a lone tube in the same stream. At this Reynolds number the aligned bank’s coefficient is within a few per cent of the staggered one’s; staggering pays at low Reynolds numbers, where the aligned bank’s inner rows hide in the wakes of the first.
n_rows = np.arange(1, 25)
staggered = [zukauskas_nusselt(Re, Pr, ST, SL, "staggered", rows=int(n), Pr_s=Pr_s) for n in n_rows]
aligned = [zukauskas_nusselt(Re, Pr, ST, SL, "aligned", rows=int(n), Pr_s=Pr_s) for n in n_rows]
single = churchill_bernstein_nusselt(V * D / nu, Pr)
low = zukauskas_nusselt(50.0, Pr, ST, SL, "aligned") / zukauskas_nusselt(50.0, Pr, ST, SL, "staggered")
print(f"20 rows: staggered Nu = {staggered[19]:.1f}, aligned Nu = {aligned[19]:.1f}; single tube {single:.1f}")
print(f"at Re = 50 the aligned bank reaches {low:.0%} of the staggered one")
assert staggered[19] == staggered[-1] and abs(aligned[19] / staggered[19] - 1) < 0.06
assert min(aligned[19], staggered[19]) > 2 * single and low < 0.9
fig, ax = plt.subplots(figsize=(6, 3.8))
ax.plot(n_rows, staggered, "o-", label="staggered")
ax.plot(n_rows, aligned, "s-", label="aligned")
ax.axhline(single, color="gray", ls="--", label="single tube (Churchill-Bernstein)")
ax.set(xlabel="number of rows", ylabel="average Nusselt number", title=f"Tube bank at Re_max = {Re:.0f}")
ax.legend()
fig.tight_layout()
plt.show()

20 rows: staggered Nu = 93.5, aligned Nu = 97.8; single tube 42.9
at Re = 50 the aligned bank reaches 89% of the staggered one
Total running time of the script: (0 minutes 0.122 seconds)