def total_power_single_channel(T_wall, w_channel, Nu_func, T_inlet, T_chamber, T_ref, p_ref, m_dot, h_channel, w_channel_margin, emmisivity, fp): """ 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 (-): Nusselt function T_inlet (K): Chamber inlet temperature T_chamber (K): Chamber outlet temperature (same as T_c in IRT) T_ref (K): Reference temperature for the Nusselt relation and flow similary parameters 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 emmisivity (-) Emmisivity of the chamber material (for calculation of radation losses) fp (- ): [description] """ ## NOTE: just a test, assumptions are a bit sloppy, and this is just to test optimization approach at this stage A_channel = w_channel * h_channel # [m^2] Channel area print("A_channel: {}".format(A_channel)) wetted_perimeter = wetted_perimeter_rectangular( w_channel=w_channel, h_channel=h_channel ) # [m] Distance of channel cross-section in contact with fluid print("wetted_perimeter: {}".format(wetted_perimeter)) # Reference length is hydraulic diameter D_hydraulic = hydraulic_diameter_rectangular( w_channel=w_channel, h_channel=h_channel) # [m] Hydraulic diameter cp = chamber_performance_from_Nu(Nu_func=Nu_func, T_inlet=T_inlet, T_chamber=T_chamber, T_ref=T_ref, T_wall=T_wall, p_ref=p_ref, m_dot=m_dot, A_channel=A_channel, L_ref=D_hydraulic, fp=fp) ## Assume single-sided heater heat chamber material through-out at T-wall, and all along the wetted perimeter heat flows equally to teh propellant A_heater = cp['A_heater'] # [m^2] assert (A_heater > 0) L_channel = A_heater / wetted_perimeter # [m] Required length of channel to achieve required heat flow print("L_channel: {}".format(L_channel)) A_chip = required_chip_area( L_channel=L_channel, w_channel=w_channel, w_channel_margin=w_channel_margin ) # [m^2] Assume radiation occurs from silicon on just a single side of the heater print("A_microheater: {}".format(A_chip)) P_radiation = radiation_loss(T=T_wall, A=A_chip, emmisivity=emmisivity) # [W] Radiation loss P_total = P_radiation + cp[ 'Q_dot'] # [W] Total power consumption, the variable to minimize print("Heat loss {}".format(P_radiation / P_total)) return P_total
def test_simple_input(self): h = 1 w = 1 exp = 4 res = chamber.wetted_perimeter_rectangular(w_channel=w, h_channel=h) self.assertEqual(res, exp) h = 4 exp = 10 res = chamber.wetted_perimeter_rectangular(w_channel=w, h_channel=h) self.assertEqual(res, exp) w = 2 exp = 12 res = chamber.wetted_perimeter_rectangular(w_channel=w, h_channel=h) self.assertEqual(res, exp)
def rectangular_multi_channel_homogenous_calculation(channel_amount, prepared_values, Nusselt_relations, pressure_drop_relations, w_channel, h_channel, m_dot, T_wall, p_inlet, fp: FluidProperties, area_ratio_contraction=None, wall_args=None): """Same as full_homogenous_calculation, but with channels combined Args: channel_amount (-): Number of channels prepared_values (dict): Dictionary with prepared thermodynamic variables Nusselt_relations (dict): Nusselt relations for different phases pressure_drop_relations (dict): Pressure drop relations for different phases and effects A_channel (m^2): Area of a single channel wetted_perimeter (m): Circumference of a single channel (fot heat flux purposes) D_hydraulic (m): Reference for Reynolds numbers etc... m_dot (kg/s): mass flow T_wall (K): Wall temperature p_ref (Pa): Pressure through channel fp (FluidProperties): Object to access propellant properties with Returns: Results {}: Return results which are relevant for optimization """ m_dot_channel = m_dot / channel_amount # [kg/s] Mass flow for a single channel A_channel = w_channel * h_channel # [m^2] Area of a single channel D_hydraulic = hydraulic_diameter_rectangular(w_channel=w_channel, h_channel=h_channel) # [m] wetted_perimeter = wetted_perimeter_rectangular(w_channel=w_channel, h_channel=h_channel) # [m] # dP_contraction = None # [Pa] Contraction pressure drop is set to None by default, so it raises obvious errors if one attemps to use it without calculating it before (0 would hide errors) # # Contraction losses must be calculated here, as this pressure drop does significantly affect heat transfer # if pressure_drop_relations is not None: # if 'contraction' in pressure_drop_relations: # area_ratio_contraction = w_channel*channel_amount / w_inlet_manifold # [-] # dP_contraction = calc_contraction_loss(dP_func=pressure_drop_relations['contraction']) # Simulation of the flow resulting in desired channel length res = full_homogenous_calculation( prepared_values=prepared_values, Nusselt_relations=Nusselt_relations, pressure_drop_relations=pressure_drop_relations, A_channel=A_channel, wetted_perimeter=wetted_perimeter, D_hydraulic=D_hydraulic, m_dot=m_dot_channel, T_wall=T_wall, p_ref=p_inlet, fp=fp, area_ratio_contraction=area_ratio_contraction, wall_args=wall_args, ) return res
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
m_dot=m_dot, h_channel=h_channel, w_channel_margin=w_channel_margin,\ emmisivity=emmissivity, fp=fp) print(x_result) # Found optimum T_superheat = x_result.x[0] # [K] w_channel = x_result.x[1] # [m] # Chamber performance following from optimum T_wall = T_chamber + T_superheat # [K] Wall temperature A_channel = w_channel * h_channel # [m^2] Channel area mass_flux = m_dot / A_channel # [kg/m^2] Used as reference for validity of many relations in micro-channel studies print("A_channel: {}".format(A_channel)) wetted_perimeter = wetted_perimeter_rectangular( w_channel=w_channel, h_channel=h_channel ) # [m] Distance of channel cross-section in contact with fluid print("wetted_perimeter: {}".format(wetted_perimeter)) # Reference length is hydraulic diameter D_hydraulic = hydraulic_diameter_rectangular( w_channel=w_channel, h_channel=h_channel) # [m] Hydraulic diameter cp = zD.chamber_performance_from_Nu(Nu_func=Nu_func, T_inlet=T_inlet, T_chamber=T_chamber,\ T_ref=T_bulk, T_wall=T_wall, p_ref=p_inlet, m_dot=m_dot, A_channel=A_channel, L_ref=D_hydraulic, fp=fp) L_channel = cp['A_heater'] / w_channel # [m] print("L_channel: {:3.4f} mm".format(L_channel * 1e3)) print("mass_flux: {}".format(mass_flux)) print("Mass flow: {:3.4f} mg/s".format(m_dot * 1e6)) ## Print all results print(ep)
'p_exit'] # [Pa] Nozzle exit pressure # Calculate ideal power h_inlet = fp.get_enthalpy(T=T_inlet, p=p_chamber) # [J/kg] Enthalpy at chamber inlet delta_h = h_chamber - h_inlet # [J/kg] Enthalpy change between inlet and chamber Pt_ideal = m_dot * delta_h # [W] Total ideal power consumption (no heat losses) ## Plot the results fig, axs = plt.subplots(5, 2) # Render the mass flow and throat width as a function of temperature and area ratios w_throat = A_throat / h_channel # [m] Throat width, determined by assuming channel depth # Find out the hydraulic diameter for a rectangular channel wetted_perimeter = wetted_perimeter_rectangular( w_channel=w_throat, h_channel=h_channel) # [m] Wetted perimeter D_hydraulic_throat = hydraulic_diameter( A=A_throat, wetted_perimeter=wetted_perimeter) # [m] Hydraulic diameter # Numpy and CoolProp don't play nicely together, so iterate over each element to calculate Reynolds's number it_AR.reset() for AR in it_AR: it_T = np.nditer(T_chamber, flags=['c_index']) for T in it_T: # Calculate Reynolds number at throat Re_throat[it_AR.index][it_T.index] = fp.get_Reynolds_from_velocity(T=T_throat[it_AR.index][it_T.index], p=p_throat[it_AR.index][it_T.index], \ L_ref=D_hydraulic_throat[it_AR.index][it_T.index], u=u_throat[it_AR.index][it_T.index]) # [-] Reynolds number at throat it_AR.reset() for AR in it_AR: # Left side of plot axs[0][0].plot(T_chamber,