# -*- coding: utf-8 -*-"""Created on Fri May 10 14:31:24 2024@author: Basile - Marie """fromconnector.mass_connectorimportMassConnectorfromcomponent.base_componentimportBaseComponentimportnumpyasnp
[docs]classTankMixer(BaseComponent):""" **Component**: Tank Mixer **Model**: Steady-state perfect mixer **Reference**: / **Description**: This model simulates a perfectly mixed tank where multiple inlet streams of the same fluid are combined into a single outlet stream. It computes the outlet specific enthalpy and mass flow rate based on an energy balance with no heat losses and no accumulation. **Assumptions**: - Steady-state operation. - Perfect mixing (single outlet enthalpy and pressure). - All inlet streams must contain the same working fluid. - All inlet pressures must be within a fixed tolerance (default: 100 Pa). - No heat exchange with the environment (adiabatic mixing). - No phase change during mixing (inherent in the use of enthalpy balance). **Connectors**: su (MassConnector): Mass connector for the suction side ((su_1, su_2, ..., su_n). ex (MassConnector): Mass connector for the exhaust side. **Parameters**: n_inlets : Number of inlet streams to be mixed [-] **Inputs**: For each inlet stream `i` from 1 to n_inlets: P_su_i: Suction side pressure. [Pa] T_su_i: Suction side temperature. [K] m_dot_su_i: Suction side mass flow flow rate. [kg/s] fluid: Working fluid [-] **Ouputs**: P_ex: Outlet pressure [Pa] (mean of inlet pressures) h_ex: Exhaust side specific enthalpy. [J/kg] """def__init__(self,n_inlets=None):super().__init__()"Status variables"self.calculable=Noneself.parametrized=Noneself.solved=False"Supply"ifn_inletsisnotNone:self.n_inlets=n_inletsself.params['n_inlets']=n_inletsforiinrange(n_inlets):# Create inlet connectors dynamically based on number of inletsinlet_num=i+1setattr(self,f"su_{inlet_num}",MassConnector())else:raiseValueError("'Mixer' model requires to set a value for its 'n_inlets' input")"Exhaust"self.ex=MassConnector()# Create single exhaust connector#%% defget_required_inputs(self):# Used in check_calculablle to see if all of the required inputs are set""" Required inputs for the Mixer: For each inlet i: - T_su_i or h_su_i : Inlet temperature or specific enthalpy [K or J/kg] - P_su_i : Inlet pressure [Pa] - fluid_su_i : Inlet fluid [-] - m_dot_su_i : Inlet mass flow rate [kg/s] """required_inputs=[]foriinrange(self.n_inlets):inlet_num=i+1required_inputs.append(f"P_su_{inlet_num}")required_inputs.append(f"T_su_{inlet_num}")required_inputs.append(f"m_dot_su_{inlet_num}")required_inputs.append(f"fluid_su_{inlet_num}")returnrequired_inputsdefget_required_parameters(self):""" General Parameters : - n_inlets : Number of inlets to the tank [-] Geometry Parameters depend on specific geometry python files. """return['n_inlets']defare_pressures_close(self,pressures,tolerance):"""Check if all values are close to each other within the specified tolerance."""reference_value=np.mean(pressures)forpressureinpressures:ifabs(pressure-reference_value)>tolerance:returnFalsereturnTruedefsolve(self):""" Solves the mixer by performing an enthalpy balance across inlets. Checks for: - Same fluid in all inlets - Pressure consistency across inlets Sets: - Outlet pressure as mean of inlet pressures - Outlet enthalpy as mass-weighted average - Outlet mass flow rate as sum of all inlet flow rates """self.check_calculable()self.check_parametrized()ifnotself.calculable:print("Component not calculable, check input")ifnotself.parametrized:print("Component not parametrized, check parameters")"1) Compute output"pressures=np.zeros(self.n_inlets)m_dot=np.zeros(self.n_inlets)fluids=[]mean_h=0foriinrange(self.n_inlets):inlet_num=i+1connector=getattr(self,f"su_{inlet_num}")pressures[i]=connector.pm_dot[i]=connector.m_dotfluids.append(connector.fluid)# if connector.h is not None:# mean_h += connector.h * connector.m_dot# elif connector.T is not None and connector.p is not None:# h = PropsSI('H', 'T', connector.T, 'P', connector.p, connector.fluid)# mean_h += h * connector.m_dot# else:# raise ValueError(f"Missing enthalpy or temperature/pressure for inlet {inlet_num}")ifconnector.hisNone:raiseValueError(f"Missing enthalpy for inlet {inlet_num}")mean_h+=connector.h*connector.m_dot# Final enthalpy and pressure computationmean_h=mean_h/(sum(m_dot))mean_p=np.mean(pressures)iflen(set(fluids))==1:# All fluids are the sametolerance=100ifself.are_pressures_close(pressures,tolerance):self.ex.set_fluid(self.su_1.fluid)self.ex.set_p(mean_p)self.ex.set_m_dot(sum(m_dot))self.ex.set_h(mean_h)self.solved=Trueelse:self.solved=Falseprint("Pressure difference between inlets exceeds tolerance.")returnelse:raiseValueError("Mixing different fluids in 'Mixer'")return