Double Pipe Heat Exchanger
Contents
1.2. Double Pipe Heat Exchanger¶
1.2.1. Experimental Goals¶
There are three basic calculations for heat exchanger design.
Rating. Given the size, geometry, entering flowrates and streaam temperatures, compute the heat transferred.
Performance. Given measurements of stream flowrates and temperatures, estimate the heat transfer coefficient.
Sizing. Given the heat transfer requirements and stream flowrates, compute the required size and other design parameters. Sizing calculations generally require consideration of heat exchanger geometry, economics, and is considerably more complex thaan rating or performance calculations.
In this experiment, you will conduct experiments and gather data needed characterize heat exchanger performance to create a preditive model for rating calculations. You will then test your models ability to predict heat exchanger performance for other operating conditions.
1.2.2. Co-Current Operation¶
1.2.2.1. Rating Calculations¶
Consider a heat exchanger in a co-current configuration. Label one end
where
where the temperture difference
In a co-current configuration, let
where
This is an initial value problem of two differential equations that can be solved numerically with scipy.integrate.solve_ivp
as demonstrated below.
The results of the temperature calculation can be used to complete the rating calculation.
where we expect
import numpy as np
import pandas as pd
from scipy.integrate import solve_ivp
# parameter values
A = 0.5 # square meters
U = 2000 # watts/square meter/deg C
qh = 600 # liter/hour
qc = 1200 # liter/hour
Cp = 4184 # Joules/kg/deg C
rho = 1.0 # 1 kg/liter
# feed temperatures
Th0 = 55.0
Tc0 = 18.0
# differential equation model
def deriv(z, y):
Th, Tc = y
dTh = -U*A*(Th - Tc)/((rho*qh/3600)*Cp)
dTc = U*A*(Th-Tc)/((rho*qc/3600)*Cp)
return [dTh, dTc]
# initial conditions
IC = [Th0, Tc0]
# evaluate solution
soln = solve_ivp(deriv, [0, 1], IC, max_step=0.01)
# plot solution
df = pd.DataFrame(soln.y.T, columns=["Th", "Tc"])
df["z"] = soln.t
ax = df.plot(x="z", style={"Th" : "r", "Tc" : "b"}, lw=2,
title="Co-current Heat Exchanger", xlabel="distance", ylabel="deg C", grid=True)
ax.plot(0, df.loc[0, "Th"], 'r.', ms=20)
ax.plot(0, df.loc[0, "Tc"], 'b.', ms=20)
[<matplotlib.lines.Line2D at 0x7fef6d803ca0>]

1.2.2.2. Measuring Heat Transfer Coefficient¶
An analytical solution for the difference
This is a first-order linear differentiaal equation with constant coefficients that can be solved by a separation of variables. One form of the solution is
where
An overall balance for the total heat transferred between the hot and cold streams is given by
Rearranging
At steady-state
The temperature dependent term multiplying
Given experimental data, these relationships can be used to estimate the heat transfer coefficient
The following code provides estimates the value of
import numpy as np
from scipy.integrate import solve_ivp
from scipy.optimize import fmin
# known parameter values
A = 5.0
qh = 600
qc = 1200
Cp = 4.0
rho = 1.0
# experimental data
z_expt = np.linspace(0, 1, 5)
Th_expt = np.array([55.0, 48.0, 42.0, 38.0, 33.0])
Tc_expt = np.array([18.0, 22.0, 25.0, 28.0, 29.0])
# LMTD calculation of heat transfer coefficient
Th0, Th1 = Th_expt[0], Th_expt[-1]
Tc0, Tc1 = Tc_expt[0], Tc_expt[-1]
# compute heat duty
Qh = rho*qh*Cp*(Th0 - Th1)
Qc = rho*qc*Cp*(Tc1 - Tc0)
Q = (Qh + Qc)/2
print(f"Heat duty = {Q:.1f} watts")
# compute number of transfer units
NTU = np.log((Th1 - Tc1)/(Th0 - Th1))
# estimate heat transfer coefficient
LMTD = ((Th1 - Tc1) - (Th0 - Tc0))/NTU
U = Q / (LMTD * A)
# display results
print(f"NTU = {-NTU:.2f}")
print(f"LMTD = {LMTD:.2f} deg C")
print(f"U (LMTD estimate) = {U:.1f} watt/deg C/m**2")
Heat duty = 52800.0 watts
NTU = 1.70
LMTD = 19.36 deg C
U (LMTD estimate) = 545.5 watt/deg C/m**2
Fitting temperature profiles
# initial estimate of fitted parameters
p_estimate = [U, Th0, Tc0]
# simulate double pipe heat exchange given parameter vector p
def double_pipe_cocurrent(z_eval, parameters):
U, Th0, Tc0 = parameters
def deriv(z, y):
Th, Tc = y
return [-U*A*(Th - Tc)/(rho*qh*Cp), U*A*(Th-Tc)/(rho*qc*Cp)]
soln = solve_ivp(deriv, [0, 1], [Th0, Tc0], t_eval=z_eval, max_step=0.01)
Th = soln.y[0,:]
Tc = soln.y[1,:]
return Th, Tc
# compute residuals between experiment and model
def residuals(p):
Th_pred, Tc_pred = double_pipe_cocurrent(z_expt, p)
return sum((Th_expt - Th_pred)**2) + sum((Tc_expt - Tc_pred)**2)
# minimize residuals
p_min = fmin(residuals, p_estimate)
U_min = p_min[0]
print(f"U (model fit) = {U_min:.1f} watt/deg C/m**2")
# compute temperature profile using the best least squares fit
z_eval = np.linspace(0, 1, 201)
Th_pred, Tc_pred = double_pipe_cocurrent(z_eval, p_min)
# plot solution
df = pd.DataFrame(np.array([z_eval, Th_pred, Tc_pred]).T, columns=["z", "Th", "Tc"])
ax = df.plot(x="z", style={"Th" : "r", "Tc" : "b"})
expt = pd.DataFrame(np.array([z_expt, Th_expt, Tc_expt]).T, columns=["z", "Th", "Tc"])
expt.plot(ax=ax, x="z", style={"Th" : "r.", "Tc" : "b."}, ms=20, grid=True,
xlabel="fractional distance z", ylabel="deg C", title=f"Co-current Heat Exchanger: U = {U_min:.1f} watts/deg/m**2")
Optimization terminated successfully.
Current function value: 8.273495
Iterations: 75
Function evaluations: 141
U (model fit) = 554.4 watt/deg C/m**2
<AxesSubplot:title={'center':'Co-current Heat Exchanger: U = 554.4 watts/deg/m**2'}, xlabel='fractional distance z', ylabel='deg C'>

1.2.2.3. Rating, revisited¶
Integrating
So that
We have a solution for the difference
Performing the integrations produces a rating equation
which provides a solution
This is an equation that predicts the heat transfer in terms of the known stream input temperatures and flowrates.
1.2.3. Counter-Current Operation¶
1.2.3.1. Rating Calculations¶
Counter-current operation requires a different method of solution. For this case we will assume the cold water stream enters at
Because of the counter-current flow,
Substitution yields
where
import matplotlib.pyplot as plt
import numpy as np
from scipy.integrate import solve_bvp
# parameter values
A = 5
U = 700
qh = 600
qc = 1200
Cp = 4.0
rho = 1.0
# feed temperatures
Th1 = 55.0
Tc0 = 18.0
# number of points
n = 201
# differential equation model
def deriv(z, y):
Th, Tc = y
return [U*A*(Th - Tc)/(rho*qh*Cp), U*A*(Th-Tc)/(rho*qc*Cp)]
def bc(y0, y1):
return [y1[0] - Th1, # bc for Th at z=1
y0[1] - Tc0] # bc for Tc at z=0
# evaluate solution
z_eval = np.linspace(0, 1, n)
y_guess = (Th1 + Tc0)*np.ones((2, n))/2 # initial guess
soln = solve_bvp(deriv, bc, z_eval, y_guess)
# plot solution
df = pd.DataFrame({"z" : z_eval, "Th" : soln.y[0, :], "Tc" : soln.y[1, :]})
ax = df.plot(x="z", style={"Th" : "r", "Tc" : "b"}, xlabel="distance", ylabel="deg C", grid=True)
ax.plot(1, df.iloc[-1, 1], "r.", ms=20)
ax.plot(0, df.iloc[0, 2], "b.", ms=20)
[<matplotlib.lines.Line2D at 0x7fef6e220850>]
