Quickstart#

The canonical hensmith example is a small methanol/water system: a shortcut distillation column (divided into a separately-costed rectifier and stripper) whose condenser and reboiler are auxiliary exchangers, a cooler on each of the column’s two products, and a flash whose feed is heated by its own auxiliary exchanger. A HeatExchangerNetwork facility added to that system integrates every heating and cooling utility in it. Once biosteam is imported the simulation takes about a second, and every number, table and figure below is output of the code shown on this page.

Build the flowsheet#

import biosteam as bst
from hensmith import HeatExchangerNetwork

bst.settings.set_thermo(['Water', 'Methanol', 'Glycerol'], cache=True)
bst.main_flowsheet.set_flowsheet('quickstart')
feed1 = bst.Stream('feed1', flow=(8000, 100, 25))
feed2 = bst.Stream('feed2', flow=(10000, 1000, 10))
D1 = bst.ShortcutColumn('D1', ins=feed1,
                        outs=('distillate', 'bottoms_product'),
                        LHK=('Methanol', 'Water'),
                        y_top=0.99, x_bot=0.01, k=2,
                        is_divided=True)
D1_H1 = bst.HXutility('D1_H1', ins=D1.outs[1], T=300)
D1_H2 = bst.HXutility('D1_H2', ins=D1.outs[0], T=300)
F1 = bst.Flash('F1', ins=feed2, outs=('vapor', 'liquid'), V=0.9, P=101325)

bst.settings.set_thermo fixes the chemicals and the property package used for every stream that follows; cache=True reuses cached chemical objects rather than recreating them. The two feeds are given as molar flow rates in kmol/hr, in the order the chemicals were declared: feed1 is 8000 water, 100 methanol and 25 glycerol, and feed2 is 10000 water, 1000 methanol and 10 glycerol.

D1 separates methanol (light key) from water (heavy key) with a shortcut method. Its condenser and reboiler are always auxiliary HXutility units of the column, each with its own heat utility, and the network integrates each of them like any other exchanger. is_divided=True costs the rectifier and stripper as two separate vessels rather than one, and matches the HeatExchangerNetwork docstring example. D1_H1 and D1_H2 cool the bottoms product and the distillate to 300 K, and each is a stand-alone exchanger in its own right. F1 flashes feed2 to 90 % vapor at 101325 Pa; the heating its feed needs is carried by an auxiliary exchanger of the flash, created when the flash is constructed and simulated as part of the flash’s own run.

Add the network#

HXN = HeatExchangerNetwork('HXN', T_min_app=5.)
sys = bst.System.from_units('sys', units=[D1, D1_H1, D1_H2, F1, HXN])

T_min_app=5. is the minimum approach temperature in K: no synthesized process exchanger is allowed to transfer heat across a temperature difference smaller than this. It is the one thermodynamic knob that sets how much integration is feasible, and it is revisited in Pinch analysis and targets. bst.System.from_units builds the system from the units given, sorting the process units into a simulation order and setting the facility aside; the network is listed among the units but is not connected to any of them.

sys.diagram()
Flowsheet of the quickstart system: feed1 enters the divided distillation column D1, whose distillate and bottoms product go to the heat exchangers D1_H2 and D1_H1; feed2 enters the flash F1, which produces vapor and liquid; the HXN heat exchanger network sits apart as an unconnected block.

The quickstart system. HXN appears as a facility with no material streams: it neither receives nor produces process material, and only reads the heat utilities of the other units. Besides the two visible exchangers D1_H1 and D1_H2, the column’s condenser and reboiler and the flash’s feed exchanger are auxiliary exchangers inside their owner units, and the network integrates those as well – 5 streams in total, of which 3 are auxiliaries.#

Flowsheet of the quickstart system: feed1 enters the divided distillation column D1, whose distillate and bottoms product go to the heat exchangers D1_H2 and D1_H1; feed2 enters the flash F1, which produces vapor and liquid; the HXN heat exchanger network sits apart as an unconnected block.

The quickstart system. HXN appears as a facility with no material streams: it neither receives nor produces process material, and only reads the heat utilities of the other units. Besides the two visible exchangers D1_H1 and D1_H2, the column’s condenser and reboiler and the flash’s feed exchanger are auxiliary exchangers inside their owner units, and the network integrates those as well – 5 streams in total, of which 3 are auxiliaries.#

Because HeatExchangerNetwork is a BioSTEAM Facility, it is simulated only after every process unit in the system has converged, so it always works with final duties. Its network_priority = -2 is the lowest of the standard facilities, which places it first among them: the chilled water package, cooling tower and boiler that follow are then sized on the loads the network has already reduced.

Simulate#

sys.simulate()

Converging the process units comes first; the network’s pinch analysis, synthesis and costing all run afterwards, in its costing step. The original streams and heat exchangers of the system are left untouched – the stream copies and the new exchangers the network creates live in a separate flowsheet named sys_HXN, after the ID of the system.

Read the savings#

print(HXN.results())
Heat exchanger network                      Units       HXN
Low pressure steam       Duty               kJ/hr -6.32e+07
                         Flow             kmol/hr -1.63e+03
                         Cost              USD/hr      -389
Chilled water            Duty               kJ/hr  4.21e+07
                         Flow             kmol/hr -2.78e+04
                         Cost              USD/hr      -211
Cooling water            Duty               kJ/hr  1.79e+07
                         Flow             kmol/hr -1.22e+04
                         Cost              USD/hr     -5.98
Purchase cost            Heat exchangers      USD  3.46e+05
Total purchase cost                           USD  3.46e+05
Installed equipment cost                      USD  1.11e+06
Utility cost                               USD/hr      -605

Every utility row of this table is a difference, not a requirement: the facility’s heat_utilities are the utilities of the new network summed with the reversed original ones, that is new - original. A negative cost is therefore a saving, and all three agents show one here: -389 USD/hr of low pressure steam, -211 USD/hr of chilled water and -5.98 USD/hr of cooling water, for a total utility cost of -605 USD/hr. The flow rows are negative for all three agents as well, so less of each utility is consumed. The duty rows carry the sign convention of the agent they belong to: the steam duty is -6.32e+07 kJ/hr, exactly the reduction in heating load reported below, while the chilled and cooling water duties are positive (4.21e+07 and 1.79e+07 kJ/hr) because cooling duties are negative to begin with, so a positive difference again means less cooling.

The capital rows are differences too, but clipped at zero. Both the network’s installed_costs['Heat exchangers'] and purchase_costs['Heat exchangers'] are max(0, new - original), the added exchanger cost – 1.11e+06 USD here. Clipping at zero means a network whose exchangers happen to be cheaper than the ones it replaces is reported as adding nothing, rather than as a capital credit.

print(f'heating utility: {HXN.original_heat_util_load:.4g} -> {HXN.actual_heat_util_load:.4g} kJ/hr')
print(f'cooling utility: {HXN.original_cool_util_load:.4g} -> {HXN.actual_cool_util_load:.4g} kJ/hr')
print(f'energy balance error: {HXN.energy_balance_percent_error:.2g} %')
print(f'added installed cost: {HXN.installed_costs["Heat exchangers"]:.3g} USD')
print(f'process exchangers: {[hx.ID for hx in HXN.new_HXs]}')
heating utility: 3.609e+08 -> 2.977e+08 kJ/hr
cooling utility: 6.201e+07 -> 1.96e+06 kJ/hr
energy balance error: -1.8e-11 %
added installed cost: 1.11e+06 USD
process exchangers: ['HX_0_2_hs', 'HX_1_4_hs', 'HX_1_2_hs', 'HX_1_3_hs']

The heating load falls from 3.609e+08 to 2.977e+08 kJ/hr, a reduction of 17.5 %; the ratio of the two, 0.82, is the value checked by the HeatExchangerNetwork docstring example. The cooling load falls from 6.201e+07 to 1.96e+06 kJ/hr, a reduction of 96.8 %: nearly all of the cooling duty of this system can be recovered into a stream that needed heating. Four process exchangers do that work, and they are the new_HXs of the network. The energy balance error, -1.8e-11 %, checks that the synthesized network moves exactly as much heat as the original one; it is computed on every synthesis and compared against acceptable_energy_balance_error.

Draw the pinch diagram#

fig, ax = HXN.plot_pinch_diagram()
Pinch diagram of the synthesized quickstart network: two blue cold streams above three red hot streams, joined by four vertical process-exchanger connectors labelled 3.34E4, 5.03E6, 3.71E7 and 1.79E7 kJ/hr, all to the right of the dashed pinch line, with hot utility circles at the outlet of both cold streams and one cold utility circle on the hot stream D1_H1 (bottoms_product).

The synthesized network, read as a pinch diagram. The two cold streams (blue, drawn left to right) are 0 D1 - reboiler and 1 F1 - heat_exchanger (feed2); the three hot streams (red, drawn right to left) are 2 D1_H1 (bottoms_product), 3 D1 - condenser (vapor) and 4 D1_H2 (distillate). Each stream is annotated with its inlet and outlet temperature and enthalpy flow. The four vertical connectors are the process exchangers, each labelled with its duty in kJ/hr: 3.34E4 between streams 1 and 4, 5.03E6 between 1 and 2, 3.71E7 between 0 and 2, and 1.79E7 between 1 and 3. Columns are ordered so that a stream meets its exchangers in flow direction, which is why stream 1 reads 3.34E4, 5.03E6, 1.79E7 from left to right. The dashed line is the pinch, separating the cold-side design on its left from the hot-side design on its right; all four exchangers of this network lie on the hot side. The open circles are the utility exchangers that finish each stream: a hot utility (red) at the outlet of both cold streams, and a single cold utility (blue) on stream 2. Streams 3 and 4 carry no circle because their remaining cooling duty is zero – process heat exchange alone brings them to their outlet temperature.#

Where to next#