Source code for exerpy.components.heat_exchanger.steam_generator

import logging

from exerpy.components.component import Component, component_registry


[docs] @component_registry class SteamGenerator(Component): r""" Class for exergy and exergoeconomic analysis of heat exchangers. This class performs exergy and exergoeconomic analysis calculations for heat exchanger components, accounting for two inlet and two outlet streams across various temperature regimes, including above and below ambient temperature, and optional dissipative behavior. Attributes ---------- E_F : float Exergy fuel of the component :math:`\dot{E}_\mathrm{F}` in :math:`\mathrm{W}`. E_P : float Exergy product of the component :math:`\dot{E}_\mathrm{P}` in :math:`\mathrm{W}`. E_D : float Exergy destruction of the component :math:`\dot{E}_\mathrm{D}` in :math:`\mathrm{W}`. epsilon : float Exergetic efficiency of the component :math:`\varepsilon` in :math:`-`. inl : dict Dictionary containing inlet stream data with mass flows and specific exergies. outl : dict Dictionary containing outlet stream data with mass flows and specific exergies. Z_costs : float Investment cost rate of the component in currency/h. C_P : float Cost of product stream :math:`\dot{C}_P` in currency/h. C_F : float Cost of fuel stream :math:`\dot{C}_F` in currency/h. C_D : float Cost of exergy destruction :math:`\dot{C}_D` in currency/h. c_P : float Specific cost of product stream (currency per unit exergy). c_F : float Specific cost of fuel stream (currency per unit exergy). r : float Relative cost difference, :math:`(c_P - c_F)/c_F`. f : float Exergoeconomic factor, :math:`\dot{Z}/(\dot{Z} + \dot{C}_D)`. Ex_C_col : dict Custom cost coefficients collection passed via `kwargs`. Notes ----- The component has several input and output streams as follows. Inlet streams: - inl[0]: Feed water inlet (high pressure) - inl[1]: Steam inlet (intermediate pressure) - inl[2]: Heat inlet (providing the heat input Q) - inl[3]: Water injection (high pressure) - inl[4]: Water injection (intermediate pressure) Outlet streams: - outl[0]: Superheated steam outlet (high pressure) - outl[1]: Superheated steam outlet (intermediate pressure) - outl[2]: Drain / Blow down outlet """ def __init__(self, **kwargs): r""" Initialize the steam generator component. Parameters ---------- **kwargs : dict Arbitrary keyword arguments. Recognized keys: - Ex_C_col (dict): custom cost coefficients, default {} - Z_costs (float): investment cost rate in currency/h, default 0.0 """ super().__init__(**kwargs)
[docs] def calc_exergy_balance(self, T0: float, p0: float, split_physical_exergy) -> None: r""" Compute the exergy balance of the steam generator. The exergy fuel is defined as follows. If `split_physical_exergy` is `True`: .. math:: \dot{E}_{\mathrm{F}} = \bigl[\dot{E}^{\mathrm{T}}_{\mathrm{out,HP}} - \dot{E}^{\mathrm{T}}_{\mathrm{in,HP}}\bigr] + \bigl[\dot{E}^{\mathrm{T}}_{\mathrm{out,IP}} - \dot{E}^{\mathrm{T}}_{\mathrm{in,IP}}\bigr] - \dot{E}^{\mathrm{T}}_{\mathrm{w,HP}} - \dot{E}^{\mathrm{T}}_{\mathrm{w,IP}} If `split_physical_exergy` is `False`: .. math:: \dot{E}_{\mathrm{F}} = \bigl[\dot{E}^{\mathrm{PH}}_{\mathrm{out,HP}} - \dot{E}^{\mathrm{PH}}_{\mathrm{in,HP}}\bigr] + \bigl[\dot{E}^{\mathrm{PH}}_{\mathrm{out,IP}} - \dot{E}^{\mathrm{PH}}_{\mathrm{in,IP}}\bigr] - \dot{E}^{\mathrm{PH}}_{\mathrm{w,HP}} - \dot{E}^{\mathrm{PH}}_{\mathrm{w,IP}} The exergy product is defined as: .. math:: \dot{E}_\mathrm{P} = \Bigl[ \dot E^{\mathrm{PH}}_{\mathrm{out,HP}} - \dot E^{\mathrm{PH}}_{\mathrm{in,HP}} \Bigr] + \Bigl[ \dot E^{\mathrm{PH}}_{\mathrm{out,IP}} - \dot E^{\mathrm{PH}}_{\mathrm{in,IP}} \Bigr] - \dot E^{\mathrm{PH}}_{\mathrm{w,HP}} - \dot E^{\mathrm{PH}}_{\mathrm{w,IP}} where the subscripts HP and IP denote high and intermediate pressure streams, respectively, and w stands for water injection. Parameters ---------- T0 : float Ambient temperature (K). p0 : float Ambient pressure (Pa). split_physical_exergy : bool Whether to split thermal and mechanical exergy. Raises ------ ValueError If required inlets or outlets are missing. """ # Ensure that all necessary streams exist required_inlets = [0] required_outlets = [0, 2] for idx in required_inlets: if idx not in self.inl: raise ValueError(f"Missing inlet stream with index {idx}.") for idx in required_outlets: if idx not in self.outl: raise ValueError(f"Missing outlet stream with index {idx}.") exergy_type = "e_T" if split_physical_exergy else "e_PH" # Calculate exergy fuel # High pressure part: Superheated steam outlet (HP) minus Feed water inlet (HP) E_F_HP = self.outl[0]["m"] * self.outl[0][exergy_type] - self.inl[0]["m"] * self.inl[0][exergy_type] # Intermediate pressure part: Superheated steam outlet (IP) minus Steam inlet (IP) E_F_IP = self.outl.get(1, {}).get("m", 0) * self.outl.get(1, {}).get(exergy_type, 0) - self.inl.get(1, {}).get( "m", 0 ) * self.inl.get(1, {}).get(exergy_type, 0) # Water injection contributions (assumed to be negative) E_F_w_inj = self.inl.get(2, {}).get("m", 0) * self.inl.get(2, {}).get(exergy_type, 0) + self.inl.get(3, {}).get( "m", 0 ) * self.inl.get(3, {}).get(exergy_type, 0) self.E_F = E_F_HP + E_F_IP - E_F_w_inj logging.warning( "Since the temperature level of the heat source of the steam generator is unknown, " "the exergy fuel of this component is calculated based on the thermal exergy value of the water streams." ) # Calculate exergy product # High pressure part: Superheated steam outlet (HP) minus Feed water inlet (HP) E_P_HP = self.outl[0]["m"] * self.outl[0]["e_PH"] - self.inl[0]["m"] * self.inl[0]["e_PH"] # Intermediate pressure part: Superheated steam outlet (IP) minus Steam inlet (IP) E_P_IP = self.outl.get(1, {}).get("m", 0) * self.outl.get(1, {}).get("e_PH", 0) - self.inl.get(1, {}).get( "m", 0 ) * self.inl.get(1, {}).get("e_PH", 0) # Water injection contributions (assumed to be negative) E_P_w_inj = self.inl.get(2, {}).get("m", 0) * self.inl.get(2, {}).get("e_PH", 0) + self.inl.get(3, {}).get( "m", 0 ) * self.inl.get(3, {}).get("e_PH", 0) self.E_P = E_P_HP + E_P_IP - E_P_w_inj # Calculate exergy destruction and efficiency self.E_D = self.E_F - self.E_P self.epsilon = self.calc_epsilon() # Log the results logging.info( f"Exergy balance of SteamGenerator {self.name} calculated: " f"E_P = {self.E_P:.2f} W, E_F = {self.E_F:.2f} W, " f"E_D = {self.E_D:.2f} W, Efficiency = {self.epsilon:.2%}" )
[docs] def aux_eqs(self, A, b, counter, T0, equations, chemical_exergy_enabled): r""" This function must be implemented in the future. The exergoeconomic analysis of SteamGenerator is not implemented yet. """ logging.error( "The exergoeconomic analysis of SteamGenerator is not implemented yet. " "This method will be implemented in a future release." ) """ Auxiliary equations for the steam generator. This function adds rows to the cost matrix A and the right-hand-side vector b to enforce the following auxiliary cost relations: (1) c_T(heat_source)/E_F = c_T(HP_outlet)/E_T(HP) + c_T(IP_outlet)/E_T(IP) - P-principle: thermal exergy costs from heat source are distributed to steam outlets (2) 1/E_M_in(HP) * C_M_in(HP) - 1/E_M_out(HP) * C_M_out(HP) = 0 - F-principle: specific mechanical exergy costs equalized between HP inlet/outlet (3) 1/E_M_in(IP) * C_M_in(IP) - 1/E_M_out(IP) * C_M_out(IP) = 0 - F-principle: specific mechanical exergy costs equalized between IP inlet/outlet (4-5) Chemical exergy cost equations (if enabled) for HP and IP streams - F-principle: specific chemical exergy costs equalized between inlets/outlets Parameters ---------- A : numpy.ndarray The current cost matrix. b : numpy.ndarray The current right-hand-side vector. counter : int The current row index in the matrix. T0 : float Ambient temperature. equations : dict Dictionary for storing equation labels. chemical_exergy_enabled : bool Flag indicating whether chemical exergy auxiliary equations should be added. Returns ------- A : numpy.ndarray The updated cost matrix. b : numpy.ndarray The updated right-hand-side vector. counter : int The updated row index. equations : dict Updated dictionary with equation labels. """
[docs] def exergoeconomic_balance(self, T0, chemical_exergy_enabled=False): r""" This function must be implemented in the future. The exergoeconomic analysis of SteamGenerator is not implemented yet. """ logging.error( "The exergoeconomic analysis of SteamGenerator is not implemented yet. " "This method will be implemented in a future release." ) """ Perform exergoeconomic balance calculations for the steam generator. This method calculates various exergoeconomic parameters including: - Cost rates of product (C_P) and fuel (C_F) - Specific cost of product (c_P) and fuel (c_F) - Cost rate of exergy destruction (C_D) - Relative cost difference (r) - Exergoeconomic factor (f) Parameters ---------- T0 : float Ambient temperature chemical_exergy_enabled : bool, optional If True, chemical exergy is considered in the calculations. Notes ----- The exergoeconomic balance considers thermal (T), chemical (CH), and mechanical (M) exergy components for the inlet and outlet streams. """ # 1) Product cost rate: HP and IP steam net physical exergy costs, minus injection C_P_hp = self.outl[0]["m"] * self.outl[0]["C_PH"] - self.inl[0]["m"] * self.inl[0]["C_PH"] C_P_ip = 0.0 if 1 in self.outl and 1 in self.inl: C_P_ip = self.outl[1]["m"] * self.outl[1]["C_PH"] - self.inl[1]["m"] * self.inl[1]["C_PH"] # Subtract water injection costs C_P_w = 0.0 if 3 in self.inl: C_P_w += self.inl[3]["m"] * self.inl[3]["C_PH"] if 4 in self.inl: C_P_w += self.inl[4]["m"] * self.inl[4]["C_PH"] self.C_P = C_P_hp + C_P_ip - C_P_w # 2) Fuel cost rate: cost of heat exergy stream self.C_F = self.inl[2]["C_T"] # 3) Specific costs and destruction cost self.c_F = self.C_F / self.E_F if self.E_F != 0 else float("nan") self.c_P = self.C_P / self.E_P if self.E_P != 0 else float("nan") self.C_D = self.C_F - self.C_P self.r = (self.c_P - self.c_F) / self.c_F if self.c_F != 0 else float("nan") self.f = self.Z_costs / (self.Z_costs + self.C_D) if (self.Z_costs + self.C_D) != 0 else float("nan")