def test_webbook_data(self): # Pick some random points of NIST webbook to calculate Prandlt numbers, instead of re-using tables of different functions # Source: https://webbook.nist.gov/cgi/fluid.cgi?T=300&PLow=1&PHigh=10&PInc=1&Applet=on&Digits=5&ID=C7727379&Action=Load&Type=IsoTherm&TUnit=K&PUnit=bar&DUnit=kg%2Fm3&HUnit=kJ%2Fkg&WUnit=m%2Fs&VisUnit=Pa*s&STUnit=N%2Fm&RefState=DEF fp = FluidProperties("nitrogen") T = 300 # [K] p = 2e5 # [Pa] exp_Pr = 0.721667851210939 res_Pr = fp.get_Prandtl(T=T, p=p) self.assertAlmostEqual(exp_Pr, res_Pr, places=2) p = 10e5 exp_Pr = 0.7279411479231152 res_Pr = fp.get_Prandtl(T=T, p=p) self.assertAlmostEqual(exp_Pr, res_Pr, places=2) # Source for 1000K : https://webbook.nist.gov/cgi/fluid.cgi?Action=Load&ID=C7727379&Type=IsoTherm&Digits=5&PLow=1&PHigh=10&PInc=1&T=1000&RefState=DEF&TUnit=K&PUnit=bar&DUnit=kg%2Fm3&HUnit=kJ%2Fkg&WUnit=m%2Fs&VisUnit=Pa*s&STUnit=N%2Fm T = 1000 # [K] p = 2e5 # [Pa] exp_Pr = 0.7359141666666666 res_Pr = fp.get_Prandtl(T=T, p=p) self.assertAlmostEqual(exp_Pr, res_Pr, places=1) T = 1000 # [K] p = 10e5 # [Pa] exp_Pr = 0.7361587678944341 res_Pr = fp.get_Prandtl(T=T, p=p) self.assertAlmostEqual(exp_Pr, res_Pr, places=1)
def prepare_single_phase_liquid(T_inlet, steps, p_ref, m_dot, fp: FluidProperties): """ Prepare numpy arrays for calculating channel length in a liquid single-phase section of a channel. NOTE: This is done to avoid recalculating arrays that are not dependent on channel geometry, therefore speeding up optimizations.\ After all, during optimization the geometry is what varies.\ Also it also ensure that temperature endpoint and enthalpy cleanly match with saturation temperature in the correct phase Args: T_inlet (K): Inlet temperature steps (-): Amount steps of dT taken to reach saturation temperature T_sat (dT = (T_sat-T_inlet)/2) p_ref (Pa): Pressure assumed constant along channel, equal to inlet pressure m_dot (kg/s): Mass flow fp (FluidProperties): Object to access propellant properties with """ T_sat = fp.get_saturation_temperature(p=p_ref) # [K] Saturation temperature assert ( T_inlet < T_sat) # Check input assert (steps > 1) # Temperature and other intermediate variable in channel section i=0...n T, dT = np.linspace(start=T_inlet, stop=T_sat, num=steps,retstep=True) # [K] Temperature T_i (also returns steps between sections) # The reference temperature for heat transfer calculations # The first value [0] should not be important. The heat transfer calculated at i is between i-1 and i # So, from T[i-1] to T[i]. So, if there reference temperature is the average dT/2 must SUBTRACTED #T_ref = T - dT/2 # [K] Reference temperature for heat transfer calculations ## Get all thermodynamic values that can be precalculated # NOTE: all last values must be replaced with the correct values for the saturated liquid state # Before the values are replaced, sometimes an error is thrown because the values are close to the saturation point # That, or NaNs and infinites show up. This shouldn't be a problem, unless the second-to-last points also start getting close to the saturation point # Enthalpy h = fp.get_enthalpy(T=T, p=p_ref) # [J/kg] Enthalpy h[-1] = fp.get_saturation_enthalpy_liquid(p=p_ref) # [J/kg] Saturation enthalpy at T_n = T_sat # Heating power required in section to increase temp by dT. Use enthalpy difference delta_h = delta_enthalpy_per_section(h=h) # [J/kg] Enthalpy difference per section Q_dot = required_power(m_dot=m_dot, delta_h=delta_h) # [W] # Density rho = fp.get_density(T=T, p=p_ref) # [kg/m^3] Density rho[-1] = fp.get_liquid_density_at_psat(p_sat=p_ref) # [kg/m^3] Saturation density # Prandtl number Pr = fp.get_Prandtl(T=T, p=p_ref) # [-] Prandtl number Pr[-1] = fp.get_saturation_Prandtl_liquid(p_sat=p_ref) # [-] Saturation Prandtl # Thermal conductivity kappa = fp.get_thermal_conductivity(T=T, p=p_ref) # [W/(m*K)] Conductivity kappa[-1] = fp.get_liquid_saturation_conductivity(p_sat=p_ref) # [W/(m*K)] Saturation conductivity # Viscosity mu = fp.get_viscosity(T=T, p=p_ref) # [Pa*s] Viscosity mu[-1] = fp.get_liquid_saturation_viscosity(p_sat=p_ref) # [Pa*s] Saturation viscosity return {\ "T":T, # [K] "dT": dT, # [K] "rho": rho, # [kg/m^3] "h": h, # [J/kg] "Q_dot": Q_dot, # [W] "Pr": Pr, # [-] "kappa": kappa, # [W/(m*K)] "mu": mu, # [Pa*s] }
def prepare_single_phase_gas(T_outlet, steps, p_ref, m_dot, fp: FluidProperties): T_sat = fp.get_saturation_temperature(p=p_ref) # [K] Saturation temperature assert (T_outlet > T_sat) assert (steps > 1) # Temperature and other intermediate variable in channel section i=0...n T, dT = np.linspace(start=T_sat, stop=T_outlet, num=steps, retstep=True) # [K] Temperature T_i # The reference temperature for heat transfer calculations # The first value [0] should not be important. The heat transfer calculated at i is between i-1 and i # So, from T[i-1] to T[i]. So, if there reference temperature is the average dT/2 must SUBTRACTED #T_ref = T - dT/2 # [K] Reference temperature for heat transfer calculations ## Get all thermodynamic values that can be precalculated # NOTE: all first values must be replaced with the correct values for the saturated gas state # Before the values are replaced, sometimes an error is thrown because the values are close to the saturation point # That, or NaNs and infinites show up. This shouldn't be a problem, unless the second-to-last points also start getting close to the saturation point # Enthalpy h = fp.get_enthalpy(T=T, p=p_ref) # [J/kg] Enthalpy h[0] = fp.get_saturation_enthalpy_gas(p=p_ref) # [J/kg] Saturation enthalpy at T_n = T_sat # Heating power required in section to increase temp by dT. Use enthalpy difference delta_h = delta_enthalpy_per_section(h=h) # [J/kg] Enthalpy difference per section Q_dot = required_power(m_dot=m_dot, delta_h=delta_h) # [W] # Density rho = fp.get_density(T=T, p=p_ref) # [kg/m^3] Density rho[0] = fp.get_vapour_density_at_psat(p_sat=p_ref) # [kg/m^3] Saturation density # Prandtl number Pr = fp.get_Prandtl(T=T, p=p_ref) # [-] Prandtl number Pr[0] = fp.get_saturation_Prandtl_gas(p_sat=p_ref) # [-] Saturation Prandtl # Thermal conductivity kappa = fp.get_thermal_conductivity(T=T, p=p_ref) # [W/(m*K)] Conductivity kappa[0] = fp.get_gas_saturation_conductivity(p_sat=p_ref) # [W/(m*K)] Saturation conductivity # Viscosity mu = fp.get_viscosity(T=T, p=p_ref) # [Pa*s] Viscosity mu[0] = fp.get_gas_saturation_viscosity(p_sat=p_ref) # [Pa*s] Saturation viscosity return {\ "T":T, # [K] "dT": dT, # [K] "rho": rho, # [kg/m^3] "h": h, # [J/kg] "Q_dot": Q_dot, # [W] "Pr": Pr, # [-] "kappa": kappa, # [W/(m*K)] "mu": mu, # [Pa*s] }
def test_one(self): # Simply re-using case above, only heating fp = FluidProperties("HEOS::Water") T_inlet = 700 # [K] T_outlet = 900 # [K] # This makes the bulk temperature 800 K p = 5e5 # [Pa] D_h = 1e-3 u = 1e-3 T_bulk = (T_outlet + T_inlet) / 2 Re = fp.get_Reynolds_from_velocity(T=T_bulk, p=p, L_ref=D_h, u=u) Pr = fp.get_Prandtl(T=T_bulk, p=p) arguments = {'fp': fp, 'Re': Re, 'Pr': Pr} exp_Nu = 0.0018785745665208552 res_Nu = thermo.convection.Nu_DB(args=arguments) self.assertAlmostEqual(exp_Nu, res_Nu, delta=0.00001 * exp_Nu / res_Nu)
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
def chamber_performance_from_Nu(Nu_func, T_inlet, T_chamber, T_ref, T_wall, p_ref, m_dot, A_channel, L_ref, fp: FluidProperties): """ Function that calculates the power consumption and heating area for a specific chamber Args: Nu_func (-): Nusselt function, that implement the emperical relation of choice T_inlet (K): Chamber inlet temperature T_chamber (K): Chamber outlet temperature (same as T_chamber for IRT) T_ref (K): Reference temperature for the Nusselt relation and flow similary parameters T_wall (K): Wall temperature p_ref (Pa): Chamber pressure (no pressure drop assumed) m_dot (kg/s): Mass flow A_channel (m^2): Cross-sectional area of the chamber, through which the fluid flows L_ref (m): Reference length for Nusselt relation and flow similarty parameters fp (FluidProperties): Object from which Fluid Properties are determined Returns: dictionary with heater area, power required to heat up flow and Nusselt number """ ## Make sure all parameters are calculated at the same reference state (including velocity!) # Pr and Re parameters needed for most Nusselt relation rho_ref = fp.get_density(T=T_ref, p=p_ref) # [kg/m^3] Reference density u_ref = velocity_from_mass_flow( A=A_channel, m_dot=m_dot, rho=rho_ref) # [m/s] Speed at reference state print("u_ref {} m/s".format(u_ref)) Re_ref = fp.get_Reynolds_from_mass_flow( T=T_ref, p=p_ref, L_ref=L_ref, m_dot=m_dot, A=A_channel) # [-] Reynolds number at reference state Pr_ref = fp.get_Prandtl(T=T_ref, p=p_ref) # [-] Prandtl number at reference state # Now the Nusselt can be determined Nusselt = Nu_func(args={ 'Re': Re_ref, 'Pr': Pr_ref }) # [-] Nusselt number at given state (used for plotting purposes) Stanton = Stanton_from_Nusselt_func_and_velocity( Nu_func=Nu_func, m_dot=m_dot, A=A_channel, T_ref=T_ref, p_ref=p_ref, L_ref=L_ref, fp=fp) # [-] Stanton number at reference state h_conv = h_conv_from_Stanton(Stanton=Stanton, u=u_ref, T_ref=T_ref, p_ref=p_ref, fp=fp) # Now determine how much energy must be convected delta_h = ideal_enthalpy_change(T_inlet=T_inlet, p_inlet=p_ref, T_outlet=T_chamber, p_outlet=p_ref, fp=fp) # [J/kg] Q_dot = required_power( m_dot=m_dot, delta_h=delta_h) # [W] Required power to achieve delta_h A_heater = required_heater_area(Q_dot=Q_dot, h_conv=h_conv, T_wall=T_wall, T_ref=T_ref) # [m^2] assert (A_heater > 0) # Return a dictionary with interesting values return { 'A_heater': A_heater, 'Q_dot': Q_dot, 'Nusselt': Nusselt, 'Re_ref': Re_ref, 'Pr_ref': Pr_ref }
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']) # for Re in Reynolds:
for T in it_T: ## Make sure all parameters are calculated at the same reference state (including velocity) # Calculate all the bulk conditions required to determine the Nusselt number relation T_bulk = (T_inlet + T_chamber) / 2 # [K] Bulk temperature as reference rho_bulk = fp.get_density( T=T_bulk, p=p_inlet ) # [kg/m^3] Bulk density is required to get the correct velocity at the reference temperature u_bulk[it_T.index, :] = velocity_from_mass_flow( m_dot=m_dot, rho=rho_bulk, A=A_channel) # [m/s] The velocity at the bulk reference state Re_bulk[it_T.index, :] = fp.get_Reynolds_from_mass_flow(T=T_bulk, p=p_inlet, L_ref=Dh_channel, m_dot=m_dot, A=A_channel) # [-] Pr_bulk[it_T.index, :] = fp.get_Prandtl(T=T_bulk, p=p_inlet) # [-] # Now the convection parameters can be determined, taking care that the reference temperature and flow conditions are evaluated in the same location Nusselt[it_T.index, :] = Nu_func(args={ 'Re': Re_bulk[it_T.index, :], 'Pr': Pr_bulk[it_T.index, :] }) # [-] Not necessary, but useful for plots Stanton[it_T.index, :] = Stanton_from_Nusselt_func_and_velocity( Nu_func=Nu_func, m_dot=m_dot, A=A_channel, T_ref=T_bulk, p_ref=p_inlet, L_ref=Dh_channel, fp=fp) # [-] h_conv[it_T.index, :] = h_conv_from_Stanton(Stanton=Stanton[it_T.index, :], u=u_bulk[it_T.index, :],
AR_exit=float(AR), p_back=p_back, fp=fp) m_dot[it_AR.index][it_T.index] = ep['m_dot'] # [kg/s] Mass flow A_throat[it_AR.index][it_T.index] = ep['A_throat'] # [m^2] Throat area Isp[it_AR.index][it_T.index] = ep['Isp'] # [s] Specific impulse h_chamber[it_AR.index][it_T.index] = fp.get_enthalpy( T=float(T), p=p_chamber) # [J/kg] Enthalpy at chamber inlet # Throat stuff T_throat[it_AR.index][it_T.index] = ep[ 'T_throat'] # [K] Throat temperature p_throat[it_AR.index][it_T.index] = ep[ 'p_throat'] # [Pa] Throat pressure u_throat[it_AR.index][it_T.index] = ep[ 'u_throat'] # [K] Throat velocity Pr_throat[it_AR.index][it_T.index] = fp.get_Prandtl( T=ep['T_throat'], p=ep['p_throat']) # [-] Prandtl number in throat mu_throat[it_AR.index][it_T.index] = fp.get_viscosity( T=ep['T_throat'], p=ep['p_throat']) # [Pa*s] Dynamic viscosity in the throat # Nozzle exit stuff T_exit[it_AR.index][it_T.index] = ep[ 'T_exit'] # [K] Nozzle exit temperature p_exit[it_AR.index][it_T.index] = 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)
wetted_perimeter = wetted_perimeter_rectangular( w_channel=w_channel, h_channel=h_channel) # [m] Wetted perimeter D_h = hydraulic_diameter(A=A_channel, wetted_perimeter=wetted_perimeter) # [m] print("\n Hydraulic diameter: {:4.4f} um".format(D_h * 1e6)) # Determine remaining variables at inlet rho_inlet = fp.get_density(T=T_inlet, p=p_inlet) # [kg/m^3] cp_inlet = fp.get_cp(T=T_inlet, p=p_inlet) # [J/(kg*K)] u_inlet = velocity_from_mass_flow(m_dot=m_dot, rho=rho_inlet, A=A_channel) # [m/s] mass_flux = m_dot / A_channel # [kg/(m^2*s)] Re_Dh_inlet = fp.get_Reynolds_from_velocity( T=T_inlet, p=p_inlet, L_ref=D_h, u=u_inlet) # [-] Reynolds number at inlet, based on hydraulic diameter Pr_inlet = fp.get_Prandtl(T=T_inlet, p=p_inlet) # [-] Prandtl number at inlet print("\n----- INLET -----") print("Density: {:4.8f} kg/m^3".format(rho_inlet)) print("C_p: {:4.8f} kJ/(kg*K)".format(cp_inlet * 1e-3)) print("Flow velocity: {:3.4f} m/s".format(u_inlet)) print("Mass flux: {:3.2f} kg/(m^2*s)".format(mass_flux)) print("Re_Dh: {:4.4f}".format(Re_Dh_inlet)) print("Pr {:4.4f}".format(Pr_inlet)) rho_outlet = fp.get_density(T=T_outlet, p=p_inlet) # [kg/m^3] cp_outlet = fp.get_cp(T=T_outlet, p=p_inlet) # [J/(kg*K)] u_outlet = velocity_from_mass_flow(m_dot=m_dot, rho=rho_outlet, A=A_channel) # [m/s] Re_Dh_outlet = fp.get_Reynolds_from_velocity( T=T_outlet, p=p_inlet, L_ref=D_h,