Source code for hyperloop.Python.boundary_layer_sensitivity

from __future__ import print_function

import numpy as np
from openmdao.api import IndepVarComp, Component, Group, Problem, ExecComp
import matplotlib.pylab as plt

[docs]class BoundaryLayerSensitivity(Component): """ Notes ------ Component is not a part of the system model, but is instead intended to analyze the sensitivity of tube area to the bounday layer thickness over the pod. Can be made to calculatee based on Reynolds number accourding to flat plate assumption or to vary boundary layer to account for boundary layer suction or some other version of flow control. Params ------ gam : float Ratio of specific heats. Default value is 1.4 R : float Ideal gas constant. Default valut is 287 J/(m*K). A_pod : float cross sectional area of the pod. Default value is 1.4 m**2. Value will be taken from pod geometry module comp_inlet_area : float Inlet area of compressor. (m**2) L : float Pod length. Default value is 22 m. Value will be taken from pod geometry module prc : float Pressure ratio across compressor inlet and outlet. Default value is 12.5. Value will be taken from NPSS p_tube : float Pressure of air in tube. Default value is 850 Pa. Value will come from vacuum component T_ambient : float Tunnel ambient temperature. Default value is 298 K. mu : float Fluid dynamic viscosity. Default value is 1.846e-5 kg/(m*s) M_duct : float Maximum Mach number allowed in the duct. Default value is .95 M_diff : float Maximum Mach number allowed at compressor inlet. Default valu is .6 cp : float Specific heat of fluid. Default value is 1009 J/(kg*K) M_pod : float pod Mach number. Default value is .8 length_calc : bool True calculates boundary layer thickness. False takes boundary layer thickness as an input. Default value is false. Returns ------- A_tube : float will return optimal tunnel area based on pod Mach number pwr_comp : float will return the power that needs to be delivered to the flow by the compressor. Does not account for compressor efficiency A_bypass : float will return area of that the flow must go through to bypass pod A_inlet : float returns area of the inlet necessary to slow the flow down to M_diffuser A_duct_eff : float returns effective duct area which accounts for displacement boundary layer thickness approximation A_diff : float returns area of diffuser outlet Re : float returns free stream Reynolds number """ def __init__(self): super(BoundaryLayerSensitivity, self).__init__() self.add_param('gam', val=1.4, desc='ratio of specific heats') self.add_param('R', val=287.0, units='J/(kg*K)', desc='Ideal gas constant') self.add_param('BF', val=.9, desc='A_diff/A_pod') self.add_param('A_pod', val=3.0536, units='m**2', desc='pod area') self.add_param('L', val=20.5, units='m', desc='pod length') self.add_param('prc', val=12.5, units='m**2', desc='pressure ratio of a compressor') self.add_param('p_tube', val=850.0, units='Pa', desc='ambient pressure') self.add_param('T_ambient', val=320.0, units='K', desc='ambient temperature') self.add_param('mu', val=1.846e-5, units='kg/(m*s)', desc='dynamic viscosity') self.add_param('M_duct', val=.95, desc='maximum pod mach number') self.add_param( 'M_diff', val=.6, desc='maximum pod mach number befor entering the compressor') self.add_param('cp', val=1009.0, units='J/(kg*K)', desc='specific heat') self.add_param('delta_star', val=.14, units='m', desc='Boundary layer displacement thickness') self.add_param('M_pod', val=.8, desc='pod mach number') self.add_param('length_calc', val = False, desc = 'Determines if boundary layer is calculated or left as default') self.add_output('pwr_comp', val=0.0, units='W', desc='Compressor Power') self.add_output('A_inlet', val=0.0, units='m**2', desc='Pod inlet area') self.add_output('A_tube', val=0.0, units='m**2', desc='tube area') self.add_output('A_bypass', val=0.0, units='m**2', desc='bypass area') self.add_output('A_duct_eff', val=0.0, units='m**2', desc='effective duct area') self.add_output('A_diff', val=0.0, units='m**2', desc='Area after diffuser') self.add_output('Re', val=0.0, desc='Reynolds Number')
[docs] def solve_nonlinear(self, params, unknowns, resids): gam = params['gam'] BF = params['BF'] A_pod = params['A_pod'] L = params['L'] prc = params['prc'] p_tube = params['p_tube'] R = params['R'] T_ambient = params['T_ambient'] mu = params['mu'] M_duct = params['M_duct'] M_diff = params['M_diff'] cp = params['cp'] delta_star = params['delta_star'] M_pod = params['M_pod'] def mach_to_area(M1, M2, gam): '''(A2/A1) = f(M2)/f(M1) where f(M) = (1/M)*((2/(gam+1))*(1+((gam-1)/2)*M**2))**((gam+1)/(2*(gam-1)))''' A_ratio = (M1 / M2) * (((1.0 + ((gam - 1.0) / 2.0) * (M2**2.0)) / (1.0 + ((gam - 1.0) / 2.0) * (M1**2.0)))**( (gam + 1.0) / (2.0 * (gam - 1.0)))) return A_ratio #Define intermediate variables rho_inf = p_tube / (R * T_ambient) #Calculate density of free stream flow U_inf = M_pod * (np.sqrt((gam * R * T_ambient))) #Calculate velocity of free stream flow r_pod = np.sqrt((A_pod / np.pi)) #Calculate pod radius Re = (rho_inf * U_inf * L) / mu #Calculate length based Reynolds Number if params['length_calc']: delta_star = (.04775*L)/(Re**.2) A_diff = BF * A_pod #Calculate diffuser output area based on blockage factor input #Calculate inlet area. Inlet is necessary if free stream Mach number is greater than max compressore mach number M_diff if M_pod > M_diff: A_inlet = A_diff * mach_to_area(M_diff, M_pod, gam) else: A_inlet = A_diff eps = mach_to_area(M_pod, M_duct, gam) A_tube = (A_pod + np.pi * (((r_pod + delta_star)**2.0) - (r_pod**2.0)) - (eps * A_inlet)) / ((1.0 + (np.sqrt(eps))) * (1.0 - (np.sqrt(eps)))) pwr_comp = (rho_inf * U_inf * A_inlet) * cp * T_ambient * (1.0 + ( (gam - 1) / 2.0) * (M_pod**2)) * ((prc**((gam - 1) / gam)) - 1) A_bypass = A_tube - A_inlet A_duct_eff = A_tube - A_pod - np.pi * (( (r_pod + delta_star)**2) - (r_pod**2)) unknowns['pwr_comp'] = pwr_comp unknowns['A_inlet'] = A_inlet unknowns['A_tube'] = A_tube unknowns['A_bypass'] = A_bypass unknowns['A_duct_eff'] = A_duct_eff unknowns['A_diff'] = A_diff unknowns['Re'] = Re
if __name__ == '__main__': top = Problem() root = top.root = Group() params = ( ('delta_star', .02, {'units' : 'm'}), ('A_pod', 2.0, {'units' : 'm**2'}), ('L_pod', 22.0, {'units' : 'm'}), ('length_calc', False)) root.add('input_vars', IndepVarComp(params), promotes = ['delta_star', 'A_pod', 'L_pod', 'length_calc']) root.add('p', BoundaryLayerSensitivity()) root.connect('delta_star', 'p.delta_star') root.connect('A_pod', 'p.A_pod') root.connect('L_pod', 'p.L') root.connect('length_calc', 'p.length_calc') top.setup() top.run() print(top['p.A_tube']) delta_star = np.linspace(.02, .12, num = 50) A_pod = np.linspace(2, 3, num = 3) L = np.linspace(20.0, 40.0, num = 50) if top['length_calc']: A_tube = np.zeros((1, len(L))) for i in range(len(L)): top['L_pod'] = L[i] top.run() A_tube[0, i] = top['p.A_tube'] plt.plot(L, A_tube[0,:]) plt.show() else: A_tube = np.zeros((len(A_pod), len(delta_star))) for i in range(len(delta_star)): for j in range(len(A_pod)): top['delta_star'] = delta_star[i] top['A_pod'] = A_pod[j] top.run() A_tube[j,i] = top['p.A_tube'] plt.hold(True) line1, = plt.plot(delta_star, A_tube[0,:], 'b-', linewidth = 2.0, label = 'A_pod = 2.0 m^2') line2, = plt.plot(delta_star, A_tube[1,:], 'r-', linewidth = 2.0, label = 'A_pod = 2.5 m^2') line3, = plt.plot(delta_star, A_tube[2,:], 'g-', linewidth = 2.0, label = 'A_pod = 3.0 m^2') plt.xlabel('Displacement Boundary Layer (m)', fontsize = 16, fontweight = 'bold') plt.ylabel('Tube Cross Sectional Area (m**2)', fontsize = 16, fontweight = 'bold') plt.xlim(.02, .12) plt.legend(handles = [line1, line2, line3], loc = 2) plt.show()