def two_phase_single_channel(T_wall, w_channel, Nu_func_gas, Nu_func_liquid, T_inlet, T_chamber, p_ref, m_dot, h_channel, fp: FluidProperties, print_info=True): """ Function that calculates the total power consumption of a specific chamber, in order to optimize the chamber Args: T_wall (K): Wall temperature w_channel (m): Channel width Nu_func_gas (-): Nusselt function for gas phase Nu_func_liquid (-) Nusselt function for liquid phase T_inlet (K): Chamber inlet temperature T_chamber (K): Chamber outlet temperature (same as T_c in IRT) p_ref (Pa): Reference pressure for the Nusselt relation and flow similary parameters (same as inlet pressure as no pressure drop is assumed) m_dot (kg/s): Mass flow h_channel (m): Channel height w_channel_margin (m): The amount of margin around the chamber for structural reasons. Important because it also radiates heat fp (- ): [description] print_info(Bool): for debugging purposes """ # Calculate saturation temperature, to determine where transition from gas to liquid occurs T_sat = fp.get_saturation_temperature(p=p_ref) # [K] # Sanity check on input assert (T_chamber > T_sat) assert (T_wall > T_chamber) # Calculate the two reference temperatures for the separated phases T_bulk_gas = (T_sat + T_chamber) / 2 # [K] Bulk temperature gas phase T_bulk_liquid_multi = ( T_inlet + T_sat) / 2 # [K] Bulk temperature of liquid and multi-phase flow # Calculate the density at these reference points rho_bulk_gas = fp.get_density(T=T_bulk_gas, p=p_ref) # [kg/m^3] rho_bulk_liquid_multi = fp.get_density(T=T_bulk_liquid_multi, p=p_ref) # [kg/m^3] # Channel geometry A_channel = w_channel * h_channel # [m^2] Area through which the fluid flows wetted_perimeter = wetted_perimeter_rectangular( w_channel=w_channel, h_channel=h_channel ) # [m] Distance of channel cross-section in contact with fluid D_hydraulic = hydraulic_diameter_rectangular( w_channel=w_channel, h_channel=h_channel) # [m] Hydraulic diameter # Flow similarity parameters (for debugging and Nu calculatoin purposes) Re_bulk_gas = fp.get_Reynolds_from_mass_flow( m_dot=m_dot, p=p_ref, T=T_bulk_gas, L_ref=D_hydraulic, A=A_channel) # [-] Bulk Reynolds number in the gas phase Re_bulk_liquid_multi = fp.get_Reynolds_from_mass_flow( m_dot=m_dot, p=p_ref, T=T_bulk_liquid_multi, L_ref=D_hydraulic, A=A_channel) # [-] Bulk Reynolds number in the liquid/multi-phase Pr_bulk_gas = fp.get_Prandtl( T=T_bulk_gas, p=p_ref) # [-] Prandtl number in the gas phase Pr_bulk_liquid_multi = fp.get_Prandtl( T=T_bulk_liquid_multi, p=p_ref) # [-] Prandtl number in liquid/multi-phase Bo_sat = fp.get_Bond_number( p_sat=p_ref, L_ref=D_hydraulic ) # [-] Bond number at saturation pressure (assumed to be p_ref) # Calculate Nusselt number in both sections args_gas = { 'Re': Re_bulk_gas, # Arguments for Nusselt function (gas phase) 'Pr': Pr_bulk_gas, 'Bo': Bo_sat, } args_liquid_multi = { # Arguments for Nusselt function (liquid/multi phase) 'Re': Re_bulk_liquid_multi, 'Pr': Pr_bulk_liquid_multi, 'Bo': Bo_sat, } Nu_gas = Nu_func_gas(args=args_gas) Nu_liquid_multi = Nu_func_liquid(args=args_liquid_multi) # Calculate Stanton number in both sections St_gas = Stanton_from_Nusselt_and_velocity( Nu=Nu_gas, T_ref=T_bulk_gas, p_ref=p_ref, L_ref=D_hydraulic, m_dot=m_dot, A=A_channel, fp=fp) # [-] Stanton number in gas phase St_liquid_multi = Stanton_from_Nusselt_and_velocity( Nu_liquid_multi, T_ref=T_bulk_liquid_multi, p_ref=p_ref, L_ref=D_hydraulic, m_dot=m_dot, A=A_channel, fp=fp) # [-] Stanton number in liquid phase # Calculate velocity for convection parameter (bulk temp used as reference for phase) u_bulk_gas = velocity_from_mass_flow( A=A_channel, m_dot=m_dot, rho=rho_bulk_gas) # [m/s] Velocity at the gas bulk reference state u_bulk_liquid_multi = velocity_from_mass_flow( A=A_channel, m_dot=m_dot, rho=rho_bulk_liquid_multi ) # [m/s] Velocity at the liquid/multi-phase bulk reference state # Convective parameter h_conv_gas = h_conv_from_Stanton( Stanton=St_gas, u=u_bulk_gas, T_ref=T_bulk_gas, p_ref=p_ref, fp=fp ) # [W/(m^2*K)] Convective heat transfer coefficient at bulk gas state h_conv_liquid_multi = h_conv_from_Stanton( Stanton=St_liquid_multi, u=u_bulk_liquid_multi, T_ref=T_bulk_liquid_multi, p_ref=p_ref, fp=fp ) # [W/(m^2*K)] Convective heat transfer coefficient at bulk liquid/multi-phase state # Required specific enthalpy change for heating the separate sections h_outlet = fp.get_enthalpy( T=T_chamber, p=p_ref) # [J/kg] Specific enthalpy at the outlet h_sat_gas = fp.get_saturation_enthalpy_gas( p=p_ref) # [J/kg] Specific enthalpy of saturated gas h_inlet = fp.get_enthalpy(T=T_inlet, p=p_ref) # [J/kg] # Required specific enthalpy increases delta_h_gas = h_outlet - h_sat_gas # [J/kg] Enthalpy increase needed to go from saturated gas to outlet enthalpy delta_h_liquid_multi = h_sat_gas - h_inlet # [J/k] Enthalpy increase needed to go from inlet enthalpy to saturated gas # Required power for those enthalpy changes at the given mass flow Q_dot_gas = required_power(m_dot=m_dot, delta_h=delta_h_gas) # [W] Q_dot_liquid_multi = required_power(m_dot=m_dot, delta_h=delta_h_liquid_multi) # [W] # Required heater area to achieve the required power A_heater_gas = required_heater_area(Q_dot=Q_dot_gas, h_conv=h_conv_gas, T_wall=T_wall, T_ref=T_bulk_gas) # [m^2] A_heater_liquid_multi = required_heater_area( Q_dot=Q_dot_liquid_multi, h_conv=h_conv_liquid_multi, T_wall=T_wall, T_ref=T_bulk_liquid_multi) # [m^2] # Required length to achieve desired area L_channel_gas = A_heater_gas / wetted_perimeter # [m] Length of channel after gas is saturated L_channel_liquid_multi = A_heater_liquid_multi / wetted_perimeter # [m] Length of channel after heater L_channel = L_channel_gas + L_channel_liquid_multi # [m] L_hydrodynamic_entrance = D_hydraulic * Re_bulk_liquid_multi * 0.04 # [m] Hydrodynamic entrance to estimate if the flow is fully developed assert (h_outlet > h_sat_gas) assert (h_sat_gas > h_inlet) if (print_info): print("\n--- SPECIFIC ENTHALPY AT DIFFERENT STATIONS ---") print("h_outlet: {:4.3f} J/kg".format(h_outlet)) print("h_sat_gas: {:4.3f} J/kg".format(h_sat_gas)) print("h_inlet: {:4.3f} J/kg".format(h_inlet)) print("\n --- REQUIRED POWER ---") print("Q_dot_gas: {:2.5f} W".format(Q_dot_gas)) print("Q_dot_liquid_multi: {:2.5f} W".format(Q_dot_liquid_multi)) print("\n --- BULK GAS PHASE PARAMETERS --- ") print("u: {:3.2f} m/s".format(u_bulk_gas)) print("Nu: {}".format(Nu_gas)) print("Re: {}".format(Re_bulk_gas)) print("Pr: {}".format(Pr_bulk_gas)) print("St: {}".format(St_gas)) print("Bo_sat: {}".format(Bo_sat)) print("\n --- BULK LIQUID/MULTI-PHASE PARAMETERS ---") print("u: {:3.4f} m/s".format(u_bulk_liquid_multi)) print("Nu: {}".format(Nu_liquid_multi)) print("Re: {}".format(Re_bulk_liquid_multi)) print("Pr: {}".format(Pr_bulk_liquid_multi)) print("St: {}".format(St_liquid_multi)) print("\n --- CHARACTERISTIC GEOMETRIC VALUES --- ") print("Hydrodynamic entance length: {:3.3f} micron".format( L_hydrodynamic_entrance * 1e6)) print("Hydraulic diameter: {:3.3f} micron".format(D_hydraulic * 1e6)) print("L/D: {:4.2f} ".format(L_channel / D_hydraulic)) print("L/X_T {:4.2f}".format(L_channel / L_hydrodynamic_entrance)) print("\n --- RESULTING GEOMETRY ---") print("Total length: {:3.3f} mm".format(L_channel * 1e3)) print("Length (liquid/multi): {:3.3f} mm".format( L_channel_liquid_multi * 1e3)) print("Length (gas): {:3.4f} mm".format(L_channel_gas * 1e3)) print("Relative length (gas) {:3.3f} \%".format(L_channel_gas / L_channel * 100)) ## Return a dictionary with results and interesting intermediate values res = { "L_channel": L_channel, # [m] Total length of channel "D_hydraulic": D_hydraulic, # [m] Hydraulic diameter of channel "Nu_liquid_multi": Nu_liquid_multi, # [-] Nusselt number of liquid/multi-phase flow "Pr_bulk_liquid_multi": Pr_bulk_liquid_multi, # [-] Prandlt number of liquid/multi-phase flow "Re_bulk_liquid_multi": Re_bulk_liquid_multi, # [-] Reynolds number of liquid/multi-phase flow "St_liquid_multi": St_liquid_multi, # [-] Stanton number of liquid/multi-phase flow "h_conv_liquid_multi": h_conv_liquid_multi, # [W/(m^2*K)] Heat transfer coefficient "A_heater_liquid_multi": A_heater_liquid_multi, # [m^2] Required heater area for liquid/multi-phase flow "L_channel_liquid_multi": L_channel_liquid_multi, # [m] Length of channel to get required heater area "u_bulk_liquid_multi": u_bulk_liquid_multi, # [m/s] Bulk flow velocity of liquid/multi-phase flow "rho_bulk_liquid_multi": rho_bulk_liquid_multi, # [kg/m^3] Bulk density of liquid/multi-phase flow "T_bulk_liquid_multi": T_bulk_liquid_multi, # [K] Bulk temperature of liquid/multi-phase flow "delta_h_liquid_multi": delta_h_liquid_multi, # [J/kg] Enthalpy change from inlet to saturated gas "Q_dot_liquid_multi": Q_dot_liquid_multi, # [W] Power required for enthalpy change ## Same thing but for gas values "Nu_gas": Nu_gas, # [-] "Pr_bulk_gas": Pr_bulk_gas, # [-] "Re_bulk_gas": Re_bulk_gas, # [-] "St_gas": St_gas, # [-] "h_conv_gas": h_conv_gas, # [W/(m^2*K)] "A_heater_gas": A_heater_gas, # [m^2] "L_channel_gas": L_channel_gas, # [m] "u_bulk_gas": u_bulk_gas, # [m/s] "rho_bulk_gas": rho_bulk_gas, # [kg/m^3] "T_bulk_gas": T_bulk_gas, # [K] "delta_h_gas": delta_h_gas, # [J/kg] "Q_dot_gas": Q_dot_gas, # [W] } return res
# Range of Reynolds numbers to consider Reynolds = np.logspace(start=0, stop=2.8) D_hydraulic = np.logspace(start=-4.93, stop=-2.93) A_channel = D_hydraulic**2 Reynolds_2 = fp.get_Reynolds_from_mass_flow(T=T_liquid, p=p, L_ref=D_hydraulic, m_dot=m_dot, A=A_channel) # Range of hydraulic diameter that fit this Reynolds number #w_channel = 2*m_dot/( Reynolds_100 * mu_liquid ) - h_c # [m] #A_channel = h_c * w_channel # [m^2] #D_hydraulic = basic.chamber.hydraulic_diameter_rectangular(w_channel=w_channel,h_channel=h_c) # [m] #Reynolds_check = fp.get_Reynolds_from_mass_flow(T=T_liquid, p=p, L_ref=D_hydraulic, m_dot=m_dot, A=A_channel) # [-] Bond = fp.get_Bond_number(p_sat=p, L_ref=D_hydraulic) # [m] # Prandtl number in both reference states Pr_liquid = fp.get_Prandtl(T=T_liquid, p=p) # [-] Pr_gas = fp.get_Prandtl(T=T_gas, p=p) # [-] # Conductivity in reference state conductivity_liquid = fp.get_thermal_conductivity(T=T_liquid, p=p) Nu_DB_liquid = np.zeros_like(Reynolds) Nu_DB_gas = np.zeros_like(Reynolds) Nu_Kandlikar_liquid = np.zeros_like(Reynolds) #Nu_Kandlikar_gas = np.zeros_like(Reynolds) # Calculate Nusselt number for different relations # Iterare over Reynolds numbers # print(Reynolds) # iter_Re = np.nditer(Reynolds, flags=['c_index'])
m_dot = 200e-6 # [kg/s] A_channel = 1e-6 # [m^2] Channel cross sections D_h = 1e-6 * np.array((100, 200, 500)) # [m] Hydraulic diameters # Mass flux calculated for reference G = m_dot / A_channel # [kg/(m^2*s)] Mass flux print("Mass flux: {:3.1f} kg/(m^2*s)".format(G)) # Saturatoin conditions rho_l = fp.get_liquid_density_at_psat( p_sat=p) # [kg/m^3] Liquid density at saturation point rho_g = fp.get_vapour_density_at_psat( p_sat=p) # [kg/m^3] Vapour density at saturation point mu_l = fp.get_liquid_saturation_viscosity( p_sat=p) # [Pa*s] Viscosity at liquid saturatoin point (for Re_le) Bo = fp.get_Bond_number(p_sat=p, L_ref=D_h) # [-] Bond number # Calculate two-phase Nusselt number x = np.linspace(start=0, stop=1, num=10000) D_iter = np.nditer(D_h, flags=['c_index']) Nu_tp_laminar = np.zeros( (np.size(D_h), np.size(x) )) # [-] Storing two-phase Nusselt numbers for assumed laminar flow Nu_tp_turbulent = np.zeros_like( Nu_tp_laminar ) # [-] Storing two-phase Nusselt numbers for assumed turbulent flow for D in D_iter: i = D_iter.index # Flow parameters for entire flow as a liquid Re_le = Reynolds_from_mass_flow(
def calc_homogenous_transition(p_sat, x, alpha, T_sat, rho_l, rho_g, rho, m_dot, mu_l, mu, Pr, Pr_l, kappa, kappa_l, Q_dot, T_wall, D_hydr, wetted_perimeter, A_channel, Nu_func_tp, Nu_func_le, Nu_func_dryout, fp: FluidProperties, wall_args=None): """[summary] Args: p_sat ([type]): [description] x ([type]): [description] alpha ([type]): [description] T_sat ([type]): [description] rho_l ([type]): [description] rho_g ([type]): [description] rho ([type]): [description] m_dot ([type]): [description] mu_l ([type]): [description] mu ([type]): [description] Pr ([type]): [description] Pr_l ([type]): [description] kappa ([type]): [description] kappa_l ([type]): [description] Q_dot ([type]): [description] T_wall ([type]): [description] D_hydr ([type]): [description] wetted_perimeter ([type]): [description] A_channel ([type]): [description] Nu_func_tp ([type]): [description] Nu_func_le ([type]): [description] Nu_func_dryout ([type]): [description] fp (FluidProperties): [description] wall_args ([type], optional): [description]. Defaults to None. Returns: [type]: [description] """ # Calculate flow velocity # Homogenous assumption means that liquid and gas velocity are equal, so one of two must be calculated. # Alpha (void fraction) has already been calculated to satisfy this condition # For both velocities there will be some issues with a singularity at (x=0, alpha =0) or (x=1, alpha=1), but the overal density rho does not have this problem #u_l = (m_dot / A_channel) * ( 1 - x ) / (rho_l * ( 1- alpha )) # [m/s] #u_g = (m_dot / A_channel) * x / (rho_g * alpha) # [m/s] u = (m_dot / A_channel) / rho # [m/s] ## Calculate flow similarity/two-phase parameters that can only be known as soon as the geometry is known ## NOTE: mu is some form of weighted average and there are several ways to weight it (prepare_ function has the method) Re = Reynolds_from_mass_flow(m_dot=m_dot, A_channel=A_channel, L_ref=D_hydr, mu=mu) # [-] # Bond number Bo = fp.get_Bond_number(p_sat=p_sat,L_ref=D_hydr) # [-] Bond number # Nusselt number for entire flow as liquid (often used for two-phase relations) # NOTE: _le is often used as subscript, but _l might sometimes mean something else, such as G(1-x) * L / (A * mu_l). _le does NOT scale with (1-x) and is G * L / ( A * mu_l ) Re_le = Reynolds_from_mass_flow(m_dot=m_dot, A_channel=A_channel, L_ref=D_hydr, mu=mu_l) # [-] Use viscosity of liquid phase to get Re_le args_le = { 'Re': Re_le, 'Pr': Pr_l} Nu_le = Nu_func_le(args=args_le) # [-] Nusselt number as if entire flow was liquid. args_dryout = { 'Re': Re, 'Pr': Pr, 'kappa': kappa, 'kappa_l': kappa_l, } Nu_dryout = Nu_func_dryout(args=args_dryout) ## Actual Nusselt number args = { 'Re': Re, 'Pr': Pr_l, 'Bo': Bo, 'rho_g': rho_g, 'rho_l': rho_l, 'x': x, 'Nu_le': Nu_le, 'Nu_dryout': Nu_dryout, } Nu = Nu_func_tp(args=args) # [-] Two-phase Nusselt number # The Nusselt number is calculated in relation to liquid thermal conducitvity only h_conv = heat_transfer_coefficient_from_Nu(Nu=Nu, kappa=kappa_l, L_ref=D_hydr) # [W/(m^2 * K)] Heat transfer coefficient # For backwards compatability with test code, effect of wall temperature thickness can be activate separetly and is off by default we = None # Pass nothing to end result, if no wall arguments are passed if wall_args is not None: # If no information about wall is provided, skip this part # Call function to get dictionary of relevant wall effect parameters we = calc_wall_effect_parameters(\ h_conv=h_conv, w_channel_spacing=wall_args['w_channel_spacing'], kappa_wall=wall_args['kappa_wall'], # Thermal conductivity of the wall h_channel=wall_args['h_channel'], # NOTE: these arguments were not already passed to this function, due to earlier design choices w_channel=wall_args['w_channel'], T_wall_top=T_wall, # The temperature of the top is simply the heater temperature at the top, which was earlier set to T_wall T_wall_bottom=wall_args['T_wall_bottom'], # IMPORTANT: The bottom wall temperature is the one that must be guessed or iterated towards! T_fluid=T_sat) # The fluid temperature is equal T_wall = we['T_wall_effective'] # [K] # print("(Effective) wall temperature (K): ") # print(T_wall) # NOTE: T_wall may be replaced if T_wall is changed due to calculated wall effects A_heater = required_heater_area(Q_dot=Q_dot, h_conv=h_conv, T_wall=T_wall, T_ref=T_sat) # [m^2] Required heater area to heat up section with Q_dot delta_L = A_heater / wetted_perimeter # [m] Required channel section length for heating area #assert(np.all(delta_L>0)) L = np.cumsum(delta_L) # [m] Cumulative channel length of two-phase section # Note, now the channel length is known, the heat transfer in the plane of the bottom wall can be calculated (which must be equal to radiation heat loss) # This is only necessary if wall effects are taken into account Q_bottom_plane_heat_balance = None # [W] Is None unless calculated to prevent use if not actually calculated if we is not None: Q_bottom_plane_heat_balance = calc_bottom_plane_heat_balance( h_conv=h_conv, T_fluid=T_sat, we=we, wall_args=wall_args, delta_L=delta_L) return { 'L': L, 'delta_L': delta_L, 'u': u, 'rho': rho, 'Re': Re, 'Nu': Nu, 'Nu_le': Nu_le, 'h_conv': h_conv, 'Q_bottom_plane_heat_balance': Q_bottom_plane_heat_balance, }