QTHEN: 2. A greedy (but not excessively so) algorithm for optimising stream placement

Heat exchanger network design

A previous post described the inspiration for an optimization method for heat exchanger network design. The basic idea is that placing graphical representations of the individual hot and cold streams in a process on a two-dimensional plot can be used to identify potential process integration, the transfer of heat from a hot stream to a cold stream.

This was illustrated with this figure:

Plot of a hot stream and a cold stream showing the potential for heat exchange between the two streams.

Figure 1: Plot of a hot stream and a cold stream showing the potential for heat exchange between the two streams.

where the overlap between the projections of the hot and cold streams onto the x-axis is a measure of the potential heat that can be exchanged between the two streams.

In this post, I would like to demonstrate the potential of this graphical approach for an optimization based design procedure.

An example problem

A typical benchmark problem consists of 5 hot streams and 5 cold streams (Lewin 1998). Details in the following in table 1.

Table 1: Problem table for a heat exchanger network design problem with 5 hot streams, 5 cold streams, and 2 external utilities (Lewin 1998).
Label Tin Tout Q
  [K] [K] [kW]
H1 433 366 589
H2 522 411 1171
H3 544 422 1532
H4 500 339 2378
H5 472 339 2358
C1 355 450 1642
C2 366 478 1557
C3 311 494 1545
C4 333 433 762
C5 389 495 645
Steam 509 509  
Water 311 355  

An algorithm for graphical layout of line segments

In the previous post, we showed how we could draw hot and cold streams in a 2d temperature versus heat plot. The key insight is that an exchange of heat from a hot stream to a cold stream is possible if these two streams overlap in their projection onto the x axis and if the hot stream lies above the cold stream throughout the interval defined by their intersection in the projection. The task is to draw these streams in such a way as to maximise the amount of exchange.1

With the example in the previous post, the optimization problem would be one of considering different positions for the single cold stream when placed below the hot stream. When there are more streams, the problem is combinatorial. My solution to this problem is to define a greedy (but not excessively so) algorithm where some simple heuristics will enable the identification of hopefully good solutions.

A layout will be defined by the order in which we consider placing the streams in the graphical presentation. Given an order (a permutation list of indices, from 1 to the total number of streams), the algorithm is

for each stream s in given order
    x ← max(end point of previous stream of same type,
            position that maximises exchange with previous stream
              of opposite type)
    place line @ x
    if line placement infeasible
       shift line to the right to make match feasible
    end
end

This is a greedy algorithm in that it does not consider all possible options in the placement of an individual stream. However, if all different orderings of the streams would be considered (which would potentially take a very long time, O(n!) for n being the number of streams), the search space will include good solutions although possibly not the actual global optimum.2 There is always a trade-off between the size of a search space for optimization and the computational work required to search the space effectively. The greedy approach here should identify good solutions hopefully quickly.

Actual code (with all comments removed to minimise space):

function place(layout)
    ns = length(layout.streams)
    zeroQ = 0.0*unit(layout.streams[1].Q)
    streams = [layout.streams[layout.order[i]] for i in 1:ns]
    lines = Line[]
    lastcold = nothing
    lasthot = nothing
    for i  1:ns
        s = streams[i]
        if ishot(s)
            x = max( lasthot == nothing ? zeroQ : lasthot.p2.x,
                     lastcold == nothing ? zeroQ : lastcold.p2.x-s.Q,
                     lastcold == nothing ? zeroQ : lastcold.p1.x ) 
            hotline = Line(s, x)
            if lastcold != nothing && ! isFeasible(hotline, lastcold, layout.problem.ΔTmin)
                hotline = Line(s, lastcold.p2.x)
            end
            push!(lines, hotline)
            lasthot = hotline
        else 
            x = max(lasthot == nothing ? zeroQ : (lasthot.p2.x - s.Q),
                    lasthot == nothing ? zeroQ : lasthot.p1.x,
                    lastcold == nothing ? zeroQ : lastcold.p2.x)
            coldline = Line(s, x)
            if lasthot != nothing && ! isFeasible(lasthot, coldline, layout.problem.ΔTmin)
                coldline = makeFeasible(lasthot, coldline, layout.problem.ΔTmin)
            end
            push!(lines, coldline)
            lastcold = coldline
        end
    end   
    return lines
end

One aside: all quantities in the package, including heat duties and temperatures, have units associated with them. I use the Unitful.jl package to handle units. This is why the third line in the code is necessary:

zeroQ = 0.0*unit(layout.streams[1].Q)

as I need to consider a heat rate of 0 in the following code. This rate has to have the appropriate units so that it can be used in calculations involving heat rates.3

To illustrate what this algorithm does, consider the problem table defined above. There are 10 streams for on the order of 3 million possible orderings. One order would be as listed in the table. The result of the algorithm above for this ordering is

Plot of the hot and cold streams based on an ordering of all the hot streams followed by all the cold streams.

Figure 2: Plot of the hot and cold streams based on an ordering of all the hot streams followed by all the cold streams.

The hot streams are placed first. The first cold stream can be placed so that it lies partly below the last hot stream. The remaining cold streams are placed contiguously after that first one. This is not necessarily a good design: there is only exchange of heat between streams H5 and C1.

If we, instead, consider an order which interleaves the hot and cold streams, the resulting layout is

Plot of the hot and cold streams based on an ordering where the hot and cold streams are interleaved.

Figure 3: Plot of the hot and cold streams based on an ordering where the hot and cold streams are interleaved.

Here we see that each cold stream has been given the opportunity to be involved in a heat exchange with one of the hot streams. Further, one of the hot streams, H2, has also been placed to match with a cold stream. Stream C3 is not integrated with any hot stream, however.

The overall outcome is a potentially much better design as a significant amount of heat can be exchanged. But it's not necessarily the best we can do. To do better, we have to search the space of alternative orderings of the streams: an optimization problem.

Design of network using a nature inspired optimization method

The optimization method I use is Fresa, an evolutionary method, inspired by plant propagation, specifically one of the methods strawberries use to propagate. Fresa, out of the box so to speak, supports problems where the decision variables are real and/or integer variables in a bounded domain with or without equation based constraints. The decision variables for the heat exchanger network design problem, however, are represented by a permutation of the first n integer numbers.

To apply Fresa to such a problem, we need to define a neighbour function, a function that generates new points in the search space from a given point. For this problem, the neighbour function I have defined is

function Fresa.neighbour(l :: Layout, ϕ, domain)
    order = copy(l.order)
    nswaps = ceil(Int,(1-ϕ)*5)
    for i in 1:nswaps
        indices = rand(1:length(order), 2)
        order[reverse(indices)] = order[indices]
    end
    Layout(order, l.streams, l.problem)
end

where order is a permutation vector of the first n positive integer numbers and ϕ ∈ (0,1) is the fitness of the solution (i.e. the layout) passed to this function. The most fit solutions in a population will have fitness values close to 1; the least fit will have values closer to 0.

The function above takes a given permutation order and performs a number of swaps of 2 of the integer values in the permutation, the number of swaps being inversely related to the fitness. The most fit solutions will typically identify neighbouring solutions with only one swap; the least fit will identify neighbours with up to 5 swaps.

Using this neighbour function, we can now try to solve the heat exchanger network design problem. The best layout found, typically in less than 100 generations and around 1000 different layouts considered (around 7 seconds elapsed time), is

Plot of the optimum placement found by Fresa for the problem defined in Table [[lewinCtable]].

Figure 4: Plot of the optimum placement found by Fresa for the problem defined in Table 1.

The order in which the streams are placed is

[2, 10, 8, 3, 5, 6, 4, 7, 1, 9]

which corresponds to streams

[H2, C5, C3, H3, H5, C1, H4, C2, H1, C4]

From this graphical representation, we see that the network identified meets almost all of the heating requirements for the cold streams, all but a small bit of heating for C4. Cooling with external utilities is required for all the hot streams except for H3.

In the next post, I will discuss cases where this greedy approach is unable to find potentially better solutions, including the example presented here where better solutions are definitely possible yet cannot be represented with the current placement algorithm described above.

Blog navigation

Previous post Blog Next post
QTHEN: 1. Inspiration from visualization for heat exchanger network design Index Emacs carnival: Elevator pitch (or How I learned to love RSS for the fediverse)

You can find me on Mastodon or you can email me should you wish to comment on this entry or the whole blog.

References

Lewin, D. R. 1998. “A Generalized Method for HEN Synthesis Using Stochastic Optimization – II. The Synthesis of Cost-Optimal Networks.” Computers & Chemical Engineering 22 (10): 1387–1405. https://doi.org/10.1016/S0098-1354(98)00221-X.

Footnotes:

1

Actually, we typically will want to minimise an economic criterion. This will typically be the annualised cost of the heat exchange network. The annualised the cost includes capital costs, for building and installing the heat exchangers, and operating costs, based on the consumption of external utilities. In the table, the utilities available are included although not their costs. Refer to the paper cited above for all the costing details.

2

The next post in this series on heat exchanger network design, when I get around to writing it, will consider a larger more complex search space, one which should be able to identify optimal solutions (maybe). But the intention is to use this greedy algorithm as the basis for a two level optimization approach.

3

As a computer scientist working in process systems engineering, it dismays me that very few software packages handle units of measure properly if at all. Few modelling systems allow the use of units and, even when they do, they often cannot handle automatic conversion of units where required. There are exceptions to this, of course. Being able to handle units for all quantities that should have these makes for better software as many errors can be caught when calculations have incompatible units, for instance.

Author: Copyright © Professor Emeritus Eric S Fraga

Created: 2025-10-03 Fri 17:00

Validate