Heat Exchanging#

QSDsan: Quantitative Sustainable Design for sanitation and resource recovery systems

This module is developed by:

Part of this module is based on the biosteam package: https://github.com/BioSTEAMDevelopmentGroup/biosteam

This module is under the University of Illinois/NCSA Open Source License. Please refer to https://github.com/QSD-Group/QSDsan/blob/main/LICENSE.txt for license details.

class qsdsan.sanunits._heat_exchanging.HXprocess(ID='', ins: Sequence[Stream] | None = None, outs: Sequence[Stream] | None = (), thermo=None, init_with='Stream', F_BM_default=None, *, U=None, dT=5.0, T_lim0=None, T_lim1=None, material='Carbon steel/carbon steel', heat_exchanger_type='Floating head', N_shells=2, ft=None, phase0=None, phase1=None, H_lim0=None, H_lim1=None)#

Similar to biosteam.units.HXprocess, but can be initialized with qsdsan.SanStream and qsdsan.WasteStream.

F_BM: dict[str, float]#

All bare-module factors for each purchase cost. Defaults to values in the class attribute _F_BM_default.

F_D: dict[str, float]#

All design factors for each purchase cost item in baseline_purchase_costs.

F_M: dict[str, float]#

All material factors for each purchase cost item in baseline_purchase_costs.

F_P: dict[str, float]#

All pressure factors for each purchase cost item in baseline_purchase_costs.

H_lim0#

[float] Temperature limit of outlet stream at index 0.

H_lim1#

[float] Temperature limit of outlet stream at index 1.

N_shells#

Number of shells for LMTD correction factor method.

T_lim0#

[float] Temperature limit of outlet stream at index 0.

T_lim1#

[float] Temperature limit of outlet stream at index 1.

U#

[float] Enforced overall heat transfer coefficient (kW/m^2/K)

baseline_purchase_costs: dict[str, float]#

All baseline purchase costs without accounting for design, pressure, and material factors.

dT#

[float] Pinch temperature difference.

design_results: dict[str, object]#

All design requirements excluding utility requirements and detailed auxiliary unit requirements.

equipment_lifetime: int | dict[str, int]#

Lifetime of equipment. Defaults to values in the class attribute _default_equipment_lifetime. Use an integer to specify the lifetime for all items in the unit purchase costs. Use a dictionary to specify the lifetime of each purchase cost item.

ft#

User imposed correction factor.

heat_utilities: tuple[HeatUtility, ...]#

All heat utilities associated to unit. Cooling and heating requirements are stored here (including auxiliary requirements).

installed_costs: dict[str, float]#

All installed costs accounting for bare module, design, pressure, and material factors. Items here are automatically updated at the end of unit simulation.

line: str = 'Heat exchanger'#

class-attribute Name denoting the type of Unit class. Defaults to the class name of the first child class

parallel: dict[str, int]#

Name-number pairs of baseline purchase costs and auxiliary unit operations in parallel. Use ‘self’ to refer to the main unit. Capital and heat and power utilities in parallel will become proportional to this value.

phase0#

Enforced phase of outlet at index 0

phase1#

Enforced phase of outlet at index 1

power_utility: PowerUtility#

Electric utility associated to unit (including auxiliary requirements).

prioritize: bool#

Whether to prioritize unit operation specification within recycle loop (if any).

purchase_costs: dict[str, float]#

Itemized purchase costs (including auxiliary units) accounting for design, pressure, and material factors (i.e., F_D, F_P, F_M). Items here are automatically updated at the end of unit simulation.

responses: set[bst.GenericResponse]#

Unit design decisions that must be solved to satisfy specifications. While adding responses is optional, simulations benefit from responses by being able to predict better guesses.

run_after_specifications: bool#

Whether to run mass and energy balance after calling specification functions

total_heat_transfer#

[float] Total heat transferred in kW (not including losses).

class qsdsan.sanunits._heat_exchanging.HXutility(ID='', ins: Sequence[Stream] | None = None, outs: Sequence[Stream] | None = (), thermo=None, init_with='Stream', F_BM_default=None, include_construction=True, *, T=None, V=None, rigorous=False, U=None, H=None, heat_exchanger_type='Floating head', material='Carbon steel/carbon steel', N_shells=2, ft=None, heat_only=None, cool_only=None, heat_transfer_efficiency=None)#

Similar to biosteam.units.HXutility, but can be initialized with qsdsan.SanStream and qsdsan.WasteStream and calculate material usage based on [1].

References

F_BM: dict[str, float]#

All bare-module factors for each purchase cost. Defaults to values in the class attribute _F_BM_default.

F_D: dict[str, float]#

All design factors for each purchase cost item in baseline_purchase_costs.

F_M: dict[str, float]#

All material factors for each purchase cost item in baseline_purchase_costs.

F_P: dict[str, float]#

All pressure factors for each purchase cost item in baseline_purchase_costs.

H#

[float] Enthalpy of outlet stream.

N_shells#

Number of shells for LMTD correction factor method.

T#

[float] Temperature of outlet stream (K).

U#

[float] Enforced overall heat transfer coefficient (kW/m^2/K)

V#

[float] Vapor fraction of outlet stream.

baseline_purchase_costs: dict[str, float]#

All baseline purchase costs without accounting for design, pressure, and material factors.

cool_only#

[bool] If True, heat exchanger can only cool.

design_results: dict[str, object]#

All design requirements excluding utility requirements and detailed auxiliary unit requirements.

equipment_lifetime: int | dict[str, int]#

Lifetime of equipment. Defaults to values in the class attribute _default_equipment_lifetime. Use an integer to specify the lifetime for all items in the unit purchase costs. Use a dictionary to specify the lifetime of each purchase cost item.

ft#

User imposed correction factor.

heat_only#

[bool] If True, heat exchanger can only heat.

heat_transfer_efficiency#

[bool] User enforced heat transfer efficiency. A value less than 1 means that a fraction of heat transferred is lost to the environment. If value is None, it defaults to the heat transfer efficiency of the heat utility.

heat_utilities: tuple[HeatUtility, ...]#

All heat utilities associated to unit. Cooling and heating requirements are stored here (including auxiliary requirements).

installed_costs: dict[str, float]#

All installed costs accounting for bare module, design, pressure, and material factors. Items here are automatically updated at the end of unit simulation.

line: str = 'Heat exchanger'#

class-attribute Name denoting the type of Unit class. Defaults to the class name of the first child class

parallel: dict[str, int]#

Name-number pairs of baseline purchase costs and auxiliary unit operations in parallel. Use ‘self’ to refer to the main unit. Capital and heat and power utilities in parallel will become proportional to this value.

power_utility: PowerUtility#

Electric utility associated to unit (including auxiliary requirements).

prioritize: bool#

Whether to prioritize unit operation specification within recycle loop (if any).

purchase_costs: dict[str, float]#

Itemized purchase costs (including auxiliary units) accounting for design, pressure, and material factors (i.e., F_D, F_P, F_M). Items here are automatically updated at the end of unit simulation.

responses: set[bst.GenericResponse]#

Unit design decisions that must be solved to satisfy specifications. While adding responses is optional, simulations benefit from responses by being able to predict better guesses.

rigorous#

[bool] If true, calculate vapor liquid equilibrium

run_after_specifications: bool#

Whether to run mass and energy balance after calling specification functions

class qsdsan.sanunits._heat_exchanging.HeatExchangerNetwork(ID='', T_min_app=5.0, units=None, ignored=None, Qmin=0.001, force_ideal_thermo=False, cache_network=False, avoid_recycle=False, acceptable_energy_balance_error=None, replace_unit_heat_utilities=False)#

Similar to the biosteam.units.facilities.HeatExchangerNetwork, but also a subclass of qsdsan.SanUnit

Examples

>>> import qsdsan as qs
>>> from qsdsan import Stream, sanunits as su
>>> from qsdsan.utils import create_example_components
>>> qs.set_thermo(create_example_components())
>>> salt_water = Stream('salt_water', Water=2000, NaCl=50, units='kg/hr')
>>> methanol = Stream('methanol', Methanol=20, units='kg/hr')
>>> ethanol = Stream('ethanol', Ethanol=10, units='kg/hr')
>>> M1 = su.MixTank('M1', ins=(salt_water, 'recycled_brine', methanol, ethanol), init_with='Stream')
>>> P1 = su.Pump('P1', ins=M1-0, init_with='Stream')
>>> H1 = su.HXutility('H1', ins=P1-0, T=350, init_with='Stream')
>>> S1 = su.ComponentSplitter('S1', ins=H1-0, split_keys=('Methanol', 'Ethanol'), init_with='Stream')
>>> M2 = su.Mixer('M2', ins=(S1-0, S1-1), outs='alcohols', init_with='Stream')
>>> S2 = su.Splitter('S2', ins=S1-2, outs=(1-M1, 'waste_brine'), split=0.2, init_with='Stream')
>>> H2 = su.HXutility('H2', ins=S2.outs[1], T=280, init_with='Stream')
>>> HXN = su.HeatExchangerNetwork('HXN')
>>> sys = qs.System('sys', path=(M1, P1, H1, S1, M2, S2, H2), facilities=(HXN,))
>>> sys.simulate()
>>> # The actual utility usage is just 30% of the original one (i.e., without HXN)
>>> round(HXN.actual_heat_util_load/HXN.original_heat_util_load, 2)
0.28
>>> HXN.stream_life_cycles 
[<StreamLifeCycle: Stream_0, cold
    life_cycle = [
            <LifeStage: <HXprocess: HX_0_1_hs>, H_in = 0 kJ, H_out = 3.15e+05 kJ>
            <LifeStage: <HXutility: Util_0_hs>, H_in = 3.15e+05 kJ, H_out = 4.4e+05 kJ>
    ]>,
 <StreamLifeCycle: Stream_1, hot
    life_cycle = [
            <LifeStage: <HXprocess: HX_0_1_hs>, H_in = 3.49e+05 kJ, H_out = 3.36e+04 kJ>
            <LifeStage: <HXutility: Util_1_cs>, H_in = 3.36e+04 kJ, H_out = -1.22e+05 kJ>
    ]>]
F_BM: dict[str, float]#

All bare-module factors for each purchase cost. Defaults to values in the class attribute _F_BM_default.

F_D: dict[str, float]#

All design factors for each purchase cost item in baseline_purchase_costs.

F_M: dict[str, float]#

All material factors for each purchase cost item in baseline_purchase_costs.

F_P: dict[str, float]#

All pressure factors for each purchase cost item in baseline_purchase_costs.

baseline_purchase_costs: dict[str, float]#

All baseline purchase costs without accounting for design, pressure, and material factors.

design_results: dict[str, object]#

All design requirements excluding utility requirements and detailed auxiliary unit requirements.

equipment_lifetime: int | dict[str, int]#

Lifetime of equipment. Defaults to values in the class attribute _default_equipment_lifetime. Use an integer to specify the lifetime for all items in the unit purchase costs. Use a dictionary to specify the lifetime of each purchase cost item.

heat_utilities: tuple[HeatUtility, ...]#

All heat utilities associated to unit. Cooling and heating requirements are stored here (including auxiliary requirements).

installed_costs: dict[str, float]#

All installed costs accounting for bare module, design, pressure, and material factors. Items here are automatically updated at the end of unit simulation.

line: str = 'Heat exchanger network'#

class-attribute Name denoting the type of Unit class. Defaults to the class name of the first child class

parallel: dict[str, int]#

Name-number pairs of baseline purchase costs and auxiliary unit operations in parallel. Use ‘self’ to refer to the main unit. Capital and heat and power utilities in parallel will become proportional to this value.

power_utility: PowerUtility#

Electric utility associated to unit (including auxiliary requirements).

prioritize: bool#

Whether to prioritize unit operation specification within recycle loop (if any).

purchase_costs: dict[str, float]#

Itemized purchase costs (including auxiliary units) accounting for design, pressure, and material factors (i.e., F_D, F_P, F_M). Items here are automatically updated at the end of unit simulation.

responses: set[bst.GenericResponse]#

Unit design decisions that must be solved to satisfy specifications. While adding responses is optional, simulations benefit from responses by being able to predict better guesses.

run_after_specifications: bool#

Whether to run mass and energy balance after calling specification functions