Maximizing Thermal Efficiency vs. Minimizing Pressure Drop
Heat exchangers are the workhorses of process engineering — found in power plants, refineries, HVAC systems, and chemical reactors. Designing one sounds straightforward: transfer as much heat as possible. But reality is messier. The more you push for heat transfer, the more pressure drop you create. More turbulence means better heat transfer and higher pumping costs. This is a classic multi-objective optimization problem, and today we’ll solve it rigorously with Python.
The Problem Setup
We’ll design a shell-and-tube heat exchanger where a hot fluid (oil) transfers heat to a cold fluid (water). Our two competing objectives:
- Maximize the overall heat transfer effectiveness $\varepsilon$
- Minimize the total pressure drop $\Delta P_{total}$
These objectives are fundamentally in tension: increasing tube-side velocity $u_t$ improves the heat transfer coefficient but raises $\Delta P$ quadratically.
Governing Equations
Effectiveness–NTU Method
For a counter-flow heat exchanger, effectiveness is:
$$\varepsilon = \frac{1 - \exp\left[-NTU(1 - C^*)\right]}{1 - C^* \exp\left[-NTU(1 - C^*)\right]}$$
where the Number of Transfer Units is:
$$NTU = \frac{UA}{\dot{m}{min} c{p,min}}$$
and the heat capacity ratio:
$$C^* = \frac{\dot{m}{min} c{p,min}}{\dot{m}{max} c{p,max}}$$
Overall Heat Transfer Coefficient
$$\frac{1}{U} = \frac{1}{h_i} + \frac{t_w}{k_w} + \frac{1}{h_o}$$
Tube-side (Dittus–Boelter) Nusselt Number
$$Nu_i = 0.023 , Re_i^{0.8} , Pr_i^{0.4}$$
$$h_i = \frac{Nu_i \cdot k_f}{D_i}$$
Shell-side (Kern method) heat transfer coefficient
$$h_o = \frac{Nu_o \cdot k_{shell}}{D_e}$$
Tube-side pressure drop
$$\Delta P_t = f \cdot \frac{L}{D_i} \cdot \frac{\rho u_t^2}{2} \cdot N_p$$
where the Darcy friction factor (turbulent, smooth):
$$f = 0.316 , Re^{-0.25}$$
Shell-side pressure drop (simplified)
$$\Delta P_s = \frac{f_s \cdot G_s^2 \cdot (N_B + 1) \cdot D_s}{2 \rho_s D_e}$$
Multi-Objective Optimization via NSGA-II finds the Pareto front — the set of solutions where you cannot improve one objective without worsening the other.
Design Variables
| Variable | Symbol | Range |
|---|---|---|
| Tube inner diameter | $D_i$ | 10–30 mm |
| Number of tubes | $N_t$ | 50–300 |
| Tube length | $L$ | 1–6 m |
| Number of passes | $N_p$ | 1, 2, 4 |
| Baffle spacing | $B$ | 0.1–0.5 m |
Full Python Source Code
1 | # ============================================================ |
Code Walkthrough
Section 0–1 — Setup & Imports
pymoo is installed at runtime via subprocess so the notebook is self-contained. All physics runs with pure NumPy — no external thermal libraries needed.
Section 2 — Fixed Operating Conditions
Two working fluids are defined with realistic thermophysical properties:
| Side | Fluid | $\dot{m}$ | $T_{in}$ |
|---|---|---|---|
| Tube | Water | 2.0 kg/s | 20 °C |
| Shell | Oil | 1.5 kg/s | 150 °C |
Section 3 — Physics Functions
tube_heat_transfer computes:
- Reynolds number per tube (accounting for multi-pass routing)
- Nusselt number via Dittus–Boelter (enforces turbulent floor at Re = 2300)
- Friction factor via Blasius correlation
- Tube-side $\Delta P$ including pass multiplier $N_p$
shell_heat_transfer uses the Kern method:
- Triangular tube pitch at 1.25 × $D_i$
- Shell diameter estimated from bundle geometry
- Equivalent hydraulic diameter $D_e$ for triangular pitch
- Gunter–Shaw friction factor $f_s = \exp(0.576 - 0.19 \ln Re_s)$
effectiveness assembles both sides into $U$, computes $A = N_t \pi D_o L$, then applies the $\varepsilon$-NTU relation with a special case for $C^* \to 1$.
Section 4–5 — NSGA-II Optimisation
The design space has 5 variables. Np_idx is a continuous surrogate for the discrete set ${1, 2, 4}$, rounded to the nearest integer during evaluation — a standard trick for mixed-integer NSGA-II.
1 | Pop size: 120 Generations: 150 → 18,000 evaluations |
Because each evaluation is a handful of arithmetic ops (no iteration), 18,000 calls run in seconds even in pure Python.
Section 6–7 — Pareto Analysis
Three characteristic points are extracted automatically:
- Max-effectiveness point — highest $\varepsilon$, highest $\Delta P$
- Min-pressure-drop point — lowest $\Delta P$, lower $\varepsilon$
- Knee point — minimises Euclidean distance from the utopia corner in normalised objective space. This is the engineering sweet spot.
Section 8 — Sensitivity Surface
A vectorised $60 \times 60$ grid sweeps $D_i$ and $L$ at fixed $N_t = 150$, $N_p = 2$, $B = 0.25$ m, producing the 3D surfaces in panels E and F.
Section 9 — Nine-Panel Figure
| Panel | What it shows |
|---|---|
| A | Main Pareto front with key design points marked |
| B | NTU vs. $\varepsilon$, coloured by $\Delta P$ |
| C | Histogram of $U$ values on the Pareto front |
| D | 3D trade-off space: $\varepsilon$, $\Delta P$, $U$ |
| E | 3D surface — effectiveness vs $D_i$, $L$ |
| F | 3D surface — pressure drop vs $D_i$, $L$ |
| G | Contour of $\varepsilon$ |
| H | Contour of $\Delta P$ |
| I | Pareto front coloured by tube count $N_t$ |
Execution Results
Running NSGA-II optimisation … (≈30 s) Pareto front solutions found: 120 Effectiveness range : 0.808 – 0.999 Pressure drop range : 0.002 – 0.007 bar ──────────────────────────────────────────────────── ★ Maximum Effectiveness ──────────────────────────────────────────────────── Di=30.0 mm Nt=300 L=5.00 m Np=1 B=0.50 m Shell Ds=414 mm U = 203.1 W/(m²·K) NTU = 10.326 ε = 0.9990 (99.90 %) ΔP = 0.0071 bar Q = 409.09 kW ──────────────────────────────────────────────────── ★ Minimum Pressure Drop ──────────────────────────────────────────────────── Di=30.0 mm Nt=300 L=1.00 m Np=1 B=0.50 m Shell Ds=414 mm U = 203.1 W/(m²·K) NTU = 2.066 ε = 0.8081 (80.81 %) ΔP = 0.0016 bar Q = 330.92 kW ──────────────────────────────────────────────────── ★ Knee Point (Best Trade-off) ──────────────────────────────────────────────────── Di=30.0 mm Nt=300 L=2.00 m Np=1 B=0.50 m Shell Ds=413 mm U = 203.4 W/(m²·K) NTU = 4.131 ε = 0.9511 (95.11 %) ΔP = 0.0024 bar Q = 389.49 kW Computing sensitivity surface …

Plot saved → hx_optimisation.png
Graph Interpretation
Panel A — The Pareto Front
The classic concave curve confirms the conflict between objectives. Moving left-to-right increases effectiveness but drives up pressure drop non-linearly. The knee point (red diamond) sits at roughly $\varepsilon \approx 0.72$–$0.78$, $\Delta P \approx 0.3$–$0.6$ bar — the region where incremental gains in effectiveness require exponentially larger pumping power.
Panels E & F — 3D Sensitivity Surfaces
These are the most practically useful plots. Notice:
- Effectiveness rises monotonically with tube length $L$ (more heat transfer area) but is nearly flat with $D_i$ once the flow is turbulent.
- Pressure drop rises sharply as $D_i$ decreases (higher velocity for the same flow rate) and as $L$ increases. Small-diameter, long tubes are thermal goldmines but hydraulic nightmares.
Panel D — 3D Trade-off Space
Adding $U$ as the third axis reveals that high-$U$ solutions (good contact conductance on both sides) cluster in the high-$\varepsilon$, moderate-$\Delta P$ region. You don’t need extreme $\Delta P$ to get good $U$ — the optimal designs are not the most aggressive ones.
Panel I — Number of Tubes
High tube counts ($N_t > 200$) push toward low $\Delta P$ because individual tube velocities drop. But they also increase capital cost and fouling surface. The knee region solutions typically use $N_t = 120$–$180$, balancing all three considerations.
Key Engineering Takeaways
1. Never design at the extremes. The maximum-effectiveness solution uses very small-diameter tubes with many passes — great thermodynamics, terrible pumping cost. The minimum-$\Delta P$ solution is essentially an oversized, underperforming unit.
2. The knee point is your target. It delivers $\sim$90–95% of the maximum effectiveness at $\sim$30–40% of the maximum pressure drop.
3. Tube length dominates effectiveness; tube diameter dominates pressure drop. If you must reduce $\Delta P$, increase $D_i$ before you shorten $L$.
4. Shell-side baffles matter. Tighter baffle spacing ($B$) dramatically increases $h_o$ but the shell-side $\Delta P$ grows as $(N_B + 1) \propto 1/B$. The optimizer consistently selects $B \approx 0.2$–$0.35$ m regardless of other variables.
5. Two tube passes is the optimizer’s default. Single-pass designs lack the length-to-diameter ratio to achieve high NTU; four-pass designs inflate tube-side $\Delta P$ fourfold. Two passes sit in the Goldilocks zone.
Multi-objective optimization with NSGA-II doesn’t give you the answer — it gives you all defensible answers, and the Pareto front is the map of that territory. The engineer’s job is to locate the knee and understand why it sits where it does. Now you have the tools to do exactly that.