Two-sided heat exchanger¶
Countercurrent or parallel exchange between a hot and a cold stream with rigorous enthalpy curves on both sides, zone-wise LMTD integration, and any one of five closing specifications.
See the flowsheeting guide for worked examples.
heat_exchanger
¶
Two-sided heat exchanger: a hot and a cold stream coupled by one duty.
The fugacio.sim.units.heater block moves heat between a stream and an
unspecified utility. A real exchanger couples two process streams, and the
plant-level questions (how much area, what approach temperatures, which side
pinches, what happens to the cold outlet when the hot inlet changes) need both
sides in one model. heat_exchanger provides that: an energy balance shared by
the two streams, outlet states from each side's own property package (so a
steam-heated reboiler can run IAPWS-95 on one side and Peng-Robinson on the
other), and a rating/design relation Q = UA * LMTD that handles phase change
by integrating the duty in zones.
One specification closes the model. It can be the duty, either outlet
temperature, a minimum approach temperature (the pinch specification of heat
integration), or the exchanger size UA (or area with a coefficient
u), in which case the duty is the root of UA_required(Q) - UA = 0. That
root is found by the bracketed solver of fugacio.thermo.implicit, so the whole
exchanger is differentiable with respect to both inlets, the size, and the
pressure drops.
Counter-current and parallel (co-current) arrangements are supported. With
zones > 1 the temperature-duty curves of both streams are sampled at
intermediate duties (each through the package's isenthalpic flash, so condensing
and boiling plateaus are captured) and the log-mean driving force is applied
zone by zone, the standard treatment for exchangers with a phase change on
either side.
Classes:
| Name | Description |
|---|---|
HeatExchangerResult |
Converged two-sided exchanger. |
Functions:
| Name | Description |
|---|---|
heat_exchanger |
Exchange heat between a hot and a cold stream under one specification. |
HeatExchangerResult
¶
Bases: NamedTuple
Converged two-sided exchanger.
Attributes:
| Name | Type | Description |
|---|---|---|
hot_out |
Stream
|
Hot-side outlet |
cold_out |
Stream
|
Cold-side outlet |
duty |
Array
|
Heat transferred from the hot to the cold stream (W, positive). |
ua |
Array
|
Overall |
lmtd |
Array
|
Effective log-mean temperature difference |
area |
Array
|
Heat-transfer area (m^2) when |
approach_hot_end |
Array
|
Temperature approach at the hot-inlet end (K). |
approach_cold_end |
Array
|
Temperature approach at the hot-outlet end (K). |
min_approach |
Array
|
Smallest approach anywhere along the exchanger (K). |
hot_curve |
Array
|
Hot-side temperatures at the zone boundaries (K), inlet first. |
cold_curve |
Array
|
Cold-side temperatures at the same positions (K). |
Methods:
| Name | Description |
|---|---|
check |
Raise if a capped duty or failed flash misses the specification. |
heat_exchanger
¶
heat_exchanger(
hot: Stream,
cold: Stream,
*,
duty: ArrayLike | None = None,
t_hot_out: ArrayLike | None = None,
t_cold_out: ArrayLike | None = None,
min_approach: ArrayLike | None = None,
ua: ArrayLike | None = None,
area: ArrayLike | None = None,
u: ArrayLike | None = None,
dp_hot: ArrayLike = 0.0,
dp_cold: ArrayLike = 0.0,
flow: str = "counter",
zones: int = 1,
model: Model = None,
model_hot: Model = None,
model_cold: Model = None,
eos: CubicEOS = PR,
kij: Array | None = None,
t_init: float = 300.0,
tol: float = 1e-09,
) -> HeatExchangerResult
Exchange heat between a hot and a cold stream under one specification.
Exactly one of duty, t_hot_out, t_cold_out, min_approach,
ua, or area (with u) must be given. The duty is always positive
(heat flows from hot to cold) and is capped by the second law: the
cold outlet cannot exceed the hot inlet nor the hot outlet drop below the
cold inlet.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hot
|
Stream
|
Hot inlet stream. |
required |
cold
|
Stream
|
Cold inlet stream. |
required |
duty
|
ArrayLike | None
|
Heat transferred (W). |
None
|
t_hot_out
|
ArrayLike | None
|
Hot outlet temperature (K). |
None
|
t_cold_out
|
ArrayLike | None
|
Cold outlet temperature (K). |
None
|
min_approach
|
ArrayLike | None
|
Minimum temperature approach (K) between the two curves; the duty is raised until the tighter end (or interior zone boundary) reaches it. |
None
|
ua
|
ArrayLike | None
|
Exchanger size |
None
|
area
|
ArrayLike | None
|
Heat-transfer area (m^2), used with |
None
|
u
|
ArrayLike | None
|
Overall heat-transfer coefficient (W/m^2/K); with |
None
|
dp_hot
|
ArrayLike
|
Hot-side pressure drop (Pa). |
0.0
|
dp_cold
|
ArrayLike
|
Cold-side pressure drop (Pa). |
0.0
|
flow
|
str
|
|
'counter'
|
zones
|
int
|
Number of duty zones the driving force is integrated over. |
1
|
model
|
Model
|
Property package for both sides (see
|
None
|
model_hot
|
Model
|
Hot-side package overriding |
None
|
model_cold
|
Model
|
Cold-side package overriding |
None
|
eos
|
CubicEOS
|
Cubic EOS for the default package. |
PR
|
kij
|
Array | None
|
Binary interaction matrix for the default package. |
None
|
t_init
|
float
|
Seed for the isenthalpic outlet solves. |
300.0
|
tol
|
float
|
Tolerance of the duty root solve (relative to the duty cap). |
1e-09
|
Returns:
| Type | Description |
|---|---|
HeatExchangerResult
|
A |
HeatExchangerResult
|
the specification, the pressure drops, and the packages. |
Raises:
| Type | Description |
|---|---|
ValueError
|
if the specification is missing or ambiguous, or |