Source code for engineeringkit.thermodynamics.systems.refrigeration

r"""Refrigerators and heat pumps: coefficients of performance and their Carnot limits.

Perkins's vapour-compression machine pumps heat from a cold space; Kelvin
saw that the same machine run against the weather heats a building with
less work than the heat it delivers. Both are bounded by the reversed
Carnot cycle, whose two COPs differ by exactly one. The vapour-compression
cycle itself is run on a Peng-Robinson refrigerant.
"""

from __future__ import annotations

import numpy as np

from engineeringkit._validation import finite as _finite
from engineeringkit._validation import interval as _interval
from engineeringkit._validation import nonnegative as _nonnegative
from engineeringkit._validation import positive as _positive
from engineeringkit.thermodynamics.core.base import VaporCompressionResult
from engineeringkit.thermodynamics.systems.peng_robinson import R134A, refrigerant_properties
from engineeringkit.thermodynamics.systems.steady_flow import compression_outlet_enthalpy

__all__ = ["carnot_cop_refrigerator", "carnot_cop_heat_pump", "refrigeration_cop", "heat_pump_cop", "vapor_compression_cycle"]


[docs] def carnot_cop_refrigerator(T_hot, T_cold): r"""Coefficient of performance of a reversible refrigerator, :math:`T_c/(T_h - T_c)`. Parameters ---------- T_hot, T_cold : float Absolute temperatures of the heat sink and the cooled space [K], with :math:`T_h > T_c > 0`. Returns ------- float Maximum heat removed per unit work [-]. Notes ----- Inputs are raw SI numbers with no dimensional metadata; see :doc:`/guides/thermodynamics`. """ _finite(T_hot=T_hot, T_cold=T_cold) _positive(T_hot=T_hot, T_cold=T_cold) if np.any(np.asarray(T_hot) <= T_cold): raise ValueError("hot reservoir must be hotter") return T_cold / (T_hot - T_cold)
[docs] def carnot_cop_heat_pump(T_hot, T_cold): r"""Coefficient of performance of a reversible heat pump, :math:`T_h/(T_h - T_c)`. Parameters ---------- T_hot, T_cold : float Absolute temperatures of the heated space and the heat source [K], with :math:`T_h > T_c > 0`. Returns ------- float Maximum heat delivered per unit work [-], one more than the refrigerator COP between the same temperatures. Notes ----- Inputs are raw SI numbers with no dimensional metadata; see :doc:`/guides/thermodynamics`. References ---------- W. Thomson, "On the economy of the heating or cooling of buildings by means of currents of air," *Proc. Phil. Soc. Glasgow* 3 (1852) 269-272. """ _finite(T_hot=T_hot, T_cold=T_cold) _positive(T_hot=T_hot, T_cold=T_cold) if np.any(np.asarray(T_hot) <= T_cold): raise ValueError("hot reservoir must be hotter") return T_hot / (T_hot - T_cold)
[docs] def refrigeration_cop(q_cold, work_input): r"""Refrigerator coefficient of performance, :math:`Q_c/W`. Parameters ---------- q_cold : float Heat removed from the cold space [J or W], nonnegative. work_input : float Work (or power) supplied [J or W, as ``q_cold``], positive. Returns ------- float COP [-]. Notes ----- Inputs are raw SI numbers with no dimensional metadata; see :doc:`/guides/thermodynamics`. References ---------- J. Perkins, "Apparatus and means for producing ice, and in cooling fluids," British Patent 6662 (1834). """ _finite(q_cold=q_cold, work_input=work_input) _nonnegative(q_cold=q_cold) _positive(work_input=work_input) return q_cold / work_input
[docs] def heat_pump_cop(q_hot, work_input): r"""Heat-pump coefficient of performance, :math:`Q_h/W`. Parameters ---------- q_hot : float Heat delivered to the warm space [J or W], at least ``work_input``. work_input : float Work (or power) supplied [J or W, as ``q_hot``], positive. Returns ------- float COP [-], at least one. Notes ----- Inputs are raw SI numbers with no dimensional metadata; see :doc:`/guides/thermodynamics`. """ _finite(q_hot=q_hot, work_input=work_input) _positive(work_input=work_input) if np.any(np.asarray(q_hot) < work_input): raise ValueError("heat-pump heat output must be >= work input") return q_hot / work_input
[docs] def vapor_compression_cycle(p_evaporator, p_condenser, *, fluid=R134A, superheat=0.0, subcooling=0.0, compressor_efficiency=1.0): r"""Vapour-compression refrigeration cycle on a Peng-Robinson refrigerant. Parameters ---------- p_evaporator : float Evaporator pressure [Pa], positive and below ``p_condenser``. p_condenser : float Condenser pressure [Pa], below the fluid's critical pressure. fluid : CubicFluid, optional Refrigerant; :data:`R134A` by default. superheat : float, optional Superheat of the vapour leaving the evaporator [K], nonnegative. subcooling : float, optional Subcooling of the liquid leaving the condenser [K], nonnegative. compressor_efficiency : float, optional Isentropic efficiency of the compressor [-] in (0, 1]. Returns ------- VaporCompressionResult The four states (compressor inlet and outlet, condenser outlet, evaporator inlet), the heat absorbed and rejected and the compressor work per kilogram, and both COPs. Notes ----- Perkins's cycle: the vapour is compressed, condensed, throttled through an expansion valve at constant enthalpy and evaporated. Heat exchangers have no pressure drop. Properties come from :func:`refrigerant_properties`. Inputs are raw SI numbers with no dimensional metadata; see :doc:`/guides/thermodynamics`. References ---------- Y. A. Çengel and M. A. Boles, *Thermodynamics: An Engineering Approach*, 9th ed., New York: McGraw-Hill (2019), Ch. 11. Examples -------- >>> res = vapor_compression_cycle(0.14e6, 0.8e6) >>> round(res.cop_refrigerator, 2) 3.94 """ _positive(p_evaporator=p_evaporator, p_condenser=p_condenser) if p_evaporator >= p_condenser: raise ValueError("p_evaporator must be below p_condenser") _nonnegative(superheat=superheat, subcooling=subcooling) _interval("compressor_efficiency", compressor_efficiency, 0, 1, closed="right") suction = refrigerant_properties(fluid, p_evaporator, x=1.0) if superheat: suction = refrigerant_properties(fluid, p_evaporator, suction.T + superheat) h_s = refrigerant_properties(fluid, p_condenser, s=suction.s).h discharge = refrigerant_properties(fluid, p_condenser, h=compression_outlet_enthalpy(suction.h, h_s, compressor_efficiency)) liquid = refrigerant_properties(fluid, p_condenser, x=0.0) if subcooling: liquid = refrigerant_properties(fluid, p_condenser, liquid.T - subcooling) valve_exit = refrigerant_properties(fluid, p_evaporator, h=liquid.h) return VaporCompressionResult( fluid=fluid, labels=("compressor inlet", "compressor outlet", "condenser outlet", "evaporator inlet"), states=(suction, discharge, liquid, valve_exit), q_evaporator=suction.h - valve_exit.h, q_condenser=discharge.h - liquid.h, compressor_work=discharge.h - suction.h, )