Skip to content

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 Stream.

cold_out Stream

Cold-side outlet Stream.

duty Array

Heat transferred from the hot to the cold stream (W, positive).

ua Array

Overall U A the duty requires (W/K).

lmtd Array

Effective log-mean temperature difference Q / UA (K).

area Array

Heat-transfer area (m^2) when u was given, else nan.

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.

converged property

converged: Array

Whether energy, feasibility, and the requested specification all close.

check

check() -> None

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 U A (W/K); the duty is solved from Q = UA * LMTD.

None
area ArrayLike | None

Heat-transfer area (m^2), used with u.

None
u ArrayLike | None

Overall heat-transfer coefficient (W/m^2/K); with area gives ua and also reports the area a duty spec requires.

None
dp_hot ArrayLike

Hot-side pressure drop (Pa).

0.0
dp_cold ArrayLike

Cold-side pressure drop (Pa).

0.0
flow str

"counter" (default) or "parallel".

'counter'
zones int

Number of duty zones the driving force is integrated over.

1
model Model

Property package for both sides (see fugacio.sim.models.package_for); defaults to Peng-Robinson.

None
model_hot Model

Hot-side package overriding model.

None
model_cold Model

Cold-side package overriding model.

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, differentiable with respect to both inlets,

HeatExchangerResult

the specification, the pressure drops, and the packages.

Raises:

Type Description
ValueError

if the specification is missing or ambiguous, or flow / zones are invalid.