Source code for exerpy.components.nodes.storage

import logging

import numpy as np

from exerpy.components.component import Component, component_registry


[docs] @component_registry class Storage(Component): r""" Class for exergy and exergoeconomic analysis of a storage. This class performs exergy and exergoeconomic analysis calculations for storage components, accounting for one inlet and one outlet stream. 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`. """ def __init__(self, **kwargs): r""" Initialize the storage 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 """ self.dissipative = False super().__init__(**kwargs)
[docs] def calc_exergy_balance(self, T0: float, p0: float, split_physical_exergy) -> None: r""" Compute the exergy balance of the storage. Parameters ---------- T0 : float Ambient temperature in Kelvin. p0 : float Ambient pressure in Pascal. split_physical_exergy : bool Flag indicating whether physical exergy is split into thermal and mechanical components. Notes ----- The exergy analysis considers the cases where the storage is either charged or discharged. Case 1 (Charging): .. math:: \dot{E}_\mathrm{F} = \dot{E}_\mathrm{in}^\mathrm{PH} - \dot{E}_\mathrm{out}^\mathrm{PH} .. math:: \dot{E}_\mathrm{P} = (\dot{m}_\mathrm{in} - \dot{m}_\mathrm{out}) \cdot e_\mathrm{out}^\mathrm{PH} Case 2 (Discharging): .. math:: \dot{E}_\mathrm{F} = (\dot{m}_\mathrm{out} - \dot{m}_\mathrm{in}) \cdot e_\mathrm{out}^\mathrm{PH} .. math:: \dot{E}_\mathrm{P} = \dot{E}_\mathrm{out}^\mathrm{PH} - \dot{E}_\mathrm{in}^\mathrm{PH} """ if self.outl[0]["m"] < self.inl[0]["m"]: logging.info(f"Storage '{self.name}' is charged.") self.E_F = self.inl[0]["m"] * self.inl[0]["e_PH"] - self.outl[0]["m"] * self.outl[0]["e_PH"] self.E_P = (self.inl[0]["m"] - self.outl[0]["m"]) * self.outl[0][ "e_PH" ] # assuming that exergy is stored at the same temperature as the outlet self.E_D = self.E_F - self.E_P elif self.outl[0]["m"] > self.inl[0]["m"]: logging.info(f"Storage '{self.name}' is discharged.") self.E_F = (self.outl[0]["m"] - self.inl[0]["m"]) * self.outl[0][ "e_PH" ] # assuming that exergy is stored at the same temperature as the outlet self.E_P = self.outl[0]["m"] * self.outl[0]["e_PH"] - self.inl[0]["m"] * self.inl[0]["e_PH"] self.E_D = self.E_F - self.E_P self.epsilon = self.E_P / self.E_F if self.E_F != 0 else np.nan # Log the results. logging.info( f"Exergy balance of Storage {self.name} calculated: " f"E_F = {self.E_F:.2f} W, E_P = {self.E_P:.2f} W, E_D = {self.E_D:.2f} W, " )
[docs] def exergoeconomic_balance(self, T0, chemical_exergy_enabled=False): r""" This class has not been implemented yet! """ pass