Building a Heat Exchanger Network
At this point, you should already have something like the following:
using EnergyIntegration
using Unitful: °C
stream_data = [...]
config = IntervalsConfig()
You can then build a heat exchanger network object with:
prob = build_hen(stream_data; config)
build_hen(streams;
config = IntervalsConfig(),
mixture = nothing,
assign = nothing
)Pack a set of `EIStream` objects through the temperature-grid, bucketing, cascade, problem-table, and preprocessing pipeline into a stable `HeatExchangerNetwork`.
Arguments
streamsVector{EIStream}- List of hot and cold streams defined in SI units.
Keyword Arguments
configIntervalsConfig= IntervalsConfig()- Configuration for temperature intervals and algorithms. If `config.use_clapeyron == true`, a `mixture` must be provided.
mixture= nothing- Clapeyron EOS model or models used for property evaluation. Use `nothing` to disable Clapeyron.
assignUnion{Nothing,Dict{Symbol,Int}}= nothing- Optional mapping from stream names to indices to override automatic mapping.
Returns
Example
prob = build_hen(stream_data; config=IntervalsConfig())Once this step is complete, there are several fields you can inspect directly.
prob.streams
6-element Vector{EIStream}:
C1 Common 333.15 K -> 433.15 K 762.0 kW ( 4, 9)
H2 Common 433.15 K -> 366.15 K 589.0 kW ( 5, 7)
C3 Common 389.15 K -> 533.15 K 876.0 kW ( 2, 6)
H4 Common 522.15 K -> 411.15 K 1171.0 kW ( 3, 5)
HU1 Isoth.. 543.15 K ? kW ( 1)
CU1 Common 311.15 K -> 355.15 K ? kW ( 9,10)
Because HU1 and CU1 are utility streams whose flow rates are still to be determined, their heat duties are shown as ? kW. After the optimization step is complete, inspecting prob.streams again will show the optimal values.
prob.table
─────────────────────────────────────────────────────────────────────────────
Row H2 H4 C1 C3 heat_cascade T_upper T_lower
─────────────────────────────────────────────────────────────────────────────
1 - - - - - 538.15 538.15
2 - - - 127750.0 127750.0 538.15 517.15
3 - 833410.0 - 480580.0 -352830.0 517.15 438.15
4 - 105500.0 76200.0 60833.0 31538.0 438.15 428.15
5 193400.0 232090.0 167640.0 133830.0 -124020.0 428.15 406.15
6 105490.0 - 91440.0 73000.0 58948.0 406.15 394.15
7 290100.0 - 251460.0 - -38643.0 394.15 361.15
8 - - 7620.0 - 7620.0 361.15 360.15
9 - - 167640.0 - 167640.0 360.15 338.15
10 - - - - - 338.15 316.15
─────────────────────────────────────────────────────────────────────────────
prob.composite
────────────────────────────────────────
Row hot cold feasible_hc T
────────────────────────────────────────
1 0 0 127749 538
2 0 127749 127749 538
3 -833414 480581 0 517
4 -105495 137033 352833 438
5 -425492 301473 321295 428
6 -105492 164440 445315 406
7 -290103 251460 386367 394
8 0 7620 425010 361
9 0 167640 417390 360
10 0 0 249750 338
11 0 0 249750 316
────────────────────────────────────────
prob.intervals_cfg.forbidden_match
Dict{Tuple{Symbol, Symbol}, Tuple{Float64, Float64}}()
Now that we have both the problem table (prob.table) and the composite-curve table (prob.composite), the natural next step is to visualize them as composite-curve and grand composite-curve plots. See the next section.