def __init__(self, **kwargs): Afuel = Variable('\\bar{A}_{fuel, max}', '-', 'Non-dim. fuel area') AR = Variable('AR_w', '-', 'Wing aspect ratio') CDp = Variable('C_{D_{p_w}}', '-', 'Wing parasitic drag coefficient') CDw = Variable('C_{D_w}', '-', 'Drag coefficient, wing') CLaw = Variable('C_{L_{aw}}', '-', 'Lift curve slope, wing') CLw = Variable('C_{L_w}', '-', 'Lift coefficient, wing') CLwmax = Variable('C_{L_{wmax}}', '-', 'Max lift coefficient, wing') D = Variable('D_{wing}', 'N', 'Wing drag') Lmax = Variable('L_{max_{w}}', 'N', 'Maximum load') Lw = Variable('L_w', 'N', 'Wing lift') M = Variable('M', '-', 'Cruise Mach number') Re = Variable('Re_w', '-', 'Cruise Reynolds number (wing)') Sw = Variable('S_w', 'm^2', 'Wing area') Vinf = Variable('V_{\\infty}', 'm/s', 'Freestream velocity') Vfuel = Variable('V_{fuel, max}', 'm^3', 'Available fuel volume') Vne = Variable('V_{ne}', 'm/s', 'Never exceed velocity') W = Variable('W', 'N', 'Aircraft weight') W0 = Variable('W_0', 'N', 'Weight excluding wing') Wfuel = Variable('W_{fuel}', 'N', 'Fuel weight') Wfuelmax= Variable('W_{fuel,max}', 'N', 'Max fuel weight') Ww = Variable('W_{wing}', 'N', 'Wing weight') a = Variable('a', 'm/s', 'Speed of sound (35,000 ft)') alpha = Variable('\\alpha_w', '-', 'Wing angle of attack') amax = Variable('\\alpha_{max,w}', '-', 'Max angle of attack') b = Variable('b_w', 'm', 'Wing span') cosL = Variable('\\cos(\\Lambda)', '-', 'Cosine of quarter-chord sweep angle') croot = Variable('c_{root}', 'm', 'Wing root chord') ctip = Variable('c_{tip}', 'm', 'Wing tip chord') cwma = Variable('\\bar{c}_w', 'm', 'Mean aerodynamic chord (wing)') e = Variable('e', '-', 'Oswald efficiency factor') eta = Variable('\\eta_w', '-', 'Lift efficiency (diff b/w sectional, actual lift)') fl = Variable('f(\\lambda_w)', '-', 'Empirical efficiency function of taper') g = Variable('g', 'm/s^2', 'Gravitational acceleration') mu = Variable('\\mu', 'N*s/m^2', 'Dynamic viscosity (35,000 ft)') p = Variable('p_w', '-', 'Substituted variable = 1 + 2*taper') q = Variable('q_w', '-', 'Substituted variable = 1 + taper') rho = Variable('\\rho', 'kg/m^3', 'Air density (cruise)') rho0 = Variable('\\rho_0', 'kg/m^3', 'Air density (0 ft)') rhofuel = Variable('\\rho_{fuel}', 'kg/m^3', 'Density of fuel') tanL = Variable('\\tan(\\Lambda)', '-', 'Tangent of quarter-chord sweep angle') taper = Variable('\\lambda', '-', 'Wing taper ratio') tau = Variable('\\tau_w', '-', 'Wing thickness/chord ratio') tcap = Variable('t_{cap}' ,'-', 'Non-dim. spar cap thickness') tweb = Variable('t_{web}', '-', 'Non-dim. shear web thickness') w = Variable('w', 0.5, '-', 'Wingbox-width-to-chord ratio') #xw = Variable('x_w', 'm', 'Position of wing aerodynamic center') ymac = Variable('y_{\\bar{c}_w}', 'm', 'Spanwise location of mean aerodynamic chord') objective = D with SignomialsEnabled(): constraints = [ Lw == 0.5*rho*Vinf**2*Sw*CLw, p >= 1 + 2*taper, 2*q >= 1 + p, ymac == (b/3)*q/p, TCS([(2./3)*(1+taper+taper**2)*croot/q <= cwma], reltol=1E-2), taper == ctip/croot, TCS([Sw <= b*(croot + ctip)/2], reltol=1E-2), # [SP] # DATCOM formula (Mach number makes it SP) TCS([(AR/eta)**2*(1 + tanL**2 - M**2) + 8*pi*AR/CLaw <= (2*pi*AR/CLaw)**2]), CLw == CLaw*alpha, alpha <= amax, # Drag D == 0.5*rho*Vinf**2*Sw*CDw, CDw >= CDp + CLw**2/(pi*e*AR), Re == rho*Vinf*cwma/mu, 1 >= (2.56*CLw**5.88/(Re**1.54*tau**3.32*CDp**2.62) + 3.8e-9*tau**6.23/(CLw**0.92*Re**1.38*CDp**9.57) + 2.2e-3*Re**0.14*tau**0.033/(CLw**0.01*CDp**0.73) + 6.14e-6*CLw**6.53/(Re**0.99*tau**0.52*CDp**5.19) + 1.19e4*CLw**9.78*tau**1.76/(Re*CDp**0.91)), # Oswald efficiency # Nita, Scholz, "Estimating the Oswald factor from # basic aircraft geometrical parameters" TCS([fl >= 0.0524*taper**4 - 0.15*taper**3 + 0.1659*taper**2 - 0.0706*taper + 0.0119], reltol=1E-2), TCS([e*(1 + fl*AR) <= 1]), taper >= 0.2, # TODO Lmax == 0.5*rho0*Vne**2*Sw*CLwmax, # Fuel volume [TASOPT doc] Afuel <= w*0.92*tau, # GP approx of the signomial constraint: # Afuel <= (w - 2*tweb)*(0.92*tau - 2*tcap), Vfuel <= croot**2 * (b/6) * (1+taper+taper**2)*cosL, Wfuel <= rhofuel*Afuel*Vfuel*g, ] standalone_constraints = [W >= W0 + Ww + Wfuel, Lw == W, M == Vinf/a, ] self.standalone_constraints = standalone_constraints wb = WingBox() wb.subinplace({'A': AR, 'b': b, 'L_{max}': Lmax, 'p': p, 'q': q, 'S': Sw, 'taper': taper, '\\tau': tau, 'W_{struct}': Ww}) lc = LinkedConstraintSet([constraints, wb]) CostedConstraintSet.__init__(self, objective, lc, **kwargs)
def __init__(self, **kwargs): ARh = Variable('AR_h', '-', 'Horizontal tail aspect ratio') ARw = Variable('AR_w', '-', 'Wing aspect ratio') CD0h = Variable('C_{D_{0_h}}', '-', 'Horizontal tail parasitic drag coefficient') CDh = Variable('C_{D_h}', '-', 'Horizontal tail drag coefficient') CLah = Variable('C_{L_{ah}}', '-', 'Lift curve slope (htail)') CLah0 = Variable('C_{L_{ah_0}}', '-', 'Isolated lift curve slope (htail)') CLaw = Variable('C_{L_{aw}}', '-', 'Lift curve slope (wing)') CLh = Variable('C_{L_h}', '-', 'Lift coefficient (htail)') CLhmax = Variable('C_{L_{hmax}}', '-', 'Max lift coefficient') CLw = Variable('C_{L_w}', '-', 'Lift coefficient (wing)') Cmac = Variable('|C_{m_{ac}}|', '-', # Absolute value of CMwing 'Moment coefficient about aerodynamic centre (wing)') Cmfu = Variable('C_{m_{fuse}}', '-', 'Moment coefficient (fuselage)') D = Variable('D_{ht}', 'N', 'Horizontal tail drag') Kf = Variable('K_f', '-', 'Empirical factor for fuselage-wing interference') Lh = Variable('L_h', 'N', 'Horizontal tail downforce') Lmax = Variable('L_{{max}_h}', 'N', 'Maximum load') M = Variable('M', '-', 'Cruise Mach number') Rec = Variable('Re_{c_h}', '-', 'Cruise Reynolds number (Horizontal tail)') SM = Variable('S.M.', '-', 'Stability margin') SMmin = Variable('S.M._{min}', '-', 'Minimum stability margin') Sh = Variable('S_h', 'm^2', 'Horizontal tail area') Sw = Variable('S_w', 'm^2', 'Wing area') Vinf = Variable('V_{\\infty}', 'm/s', 'Freestream velocity') Vne = Variable('V_{ne}', 'm/s', 'Never exceed velocity') W = Variable('W_{ht}', 'N', 'Horizontal tail weight') a = Variable('a', 'm/s', 'Speed of sound (35,000 ft)') alpha = Variable('\\alpha', '-', 'Horizontal tail angle of attack') amax = Variable('\\alpha_{max,h}', '-', 'Max angle of attack, htail') bht = Variable('b_{ht}', 'm', 'Horizontal tail span') chma = Variable('\\bar{c}_{ht}', 'm', 'Mean aerodynamic chord (ht)') croot = Variable('c_{root_h}', 'm', 'Horizontal tail root chord') ctip = Variable('c_{tip_h}', 'm', 'Horizontal tail tip chord') cwma = Variable('\\bar{c}_w', 'm', 'Mean aerodynamic chord (wing)') dxlead = Variable('\\Delta x_{{lead}_h}', 'm', 'Distance from CG to horizontal tail leading edge') dxtrail = Variable('\\Delta x_{{trail}_h}', 'm', 'Distance from CG to horizontal tail trailing edge') dxw = Variable('\\Delta x_w', 'm', 'Distance from aerodynamic centre to CG') e = Variable('e_h', '-', 'Oswald efficiency factor') eta = Variable('\\eta_h', '-', ("Lift efficiency (diff between sectional and " "actual lift)")) etaht = Variable('\\eta_{ht}', '-', 'Tail efficiency') fl = Variable(r"f(\lambda_h)", '-', 'Empirical efficiency function of taper') lfuse = Variable('l_{fuse}', 'm', 'Fuselage length') lht = Variable('l_{ht}', 'm', 'Horizontal tail moment arm') mu = Variable(r'\mu', 'N*s/m^2', 'Dynamic viscosity (35,000 ft)') p = Variable('p_{ht}', '-', 'Substituted variable = 1 + 2*taper') q = Variable('q_{ht}', '-', 'Substituted variable = 1 + taper') rho = Variable(r'\rho', 'kg/m^3', 'Air density (cruise)') rho0 = Variable(r'\rho_0', 'kg/m^3', 'Air density (0 ft)') tanLh = Variable(r'\tan(\Lambda_{ht})', '-', 'tangent of horizontal tail sweep') taper = Variable(r'\lambda_h', '-', 'Horizontal tail taper ratio') tau = Variable(r'\tau_h', '-', 'Horizontal tail thickness/chord ratio') wf = Variable('w_{fuse}', 'm', 'Fuselage width') xcg = Variable('x_{CG}', 'm', 'CG location') xcght = Variable('x_{CG_{ht}}', 'm', 'Horizontal tail CG location') xw = Variable('x_w', 'm', 'Position of wing aerodynamic center') ymac = Variable('y_{\\bar{c}_{ht}}', 'm', 'Spanwise location of mean aerodynamic chord') objective = D + 0.1*W with SignomialsEnabled(): # Stability from UMich AE-481 course notes constraints = [TCS([SM + dxw/cwma + Kf*wf**2*lfuse/(CLaw*Sw*cwma) <= CLah*Sh*lht/(CLaw*Sw*cwma)]), SM >= SMmin, # Trim from UMich AE-481 course notes TCS([CLh*Sh*lht/(Sw*cwma) + Cmac >= CLw*dxw/cwma + Cmfu], reltol=0.02), Lh == 0.5*rho*Vinf**2*Sh*CLh, # Moment arm and geometry -- same as for vtail TCS([dxlead + croot <= dxtrail]), TCS([xcg + dxtrail <= lfuse], reltol=0.002), TCS([dxlead + ymac*tanLh + 0.25*chma >= lht], reltol=1e-2), # [SP] p >= 1 + 2*taper, 2*q >= 1 + p, ymac == (bht/3)*q/p, TCS([(2./3)*(1 + taper + taper**2)*croot/q >= chma]), # [SP] taper == ctip/croot, TCS([Sh <= bht*(croot + ctip)/2]), # [SP] # DATCOM formula (Mach number makes it SP) TCS([(ARh/eta)**2*(1+tanLh**2-M**2) + 8*pi*ARh/CLah0 <= (2*pi*ARh/CLah0)**2]), # Loss of tail effectiveness due to wing downwash CLah + (2*CLaw/(pi*ARw))*etaht*CLah0 <= CLah0*etaht, CLh == CLah*alpha, alpha <= amax, # K_f as f(wing position) -- (fitted posynomial) # from from UMich AE-481 course notes Table 9.1 Kf >= (1.5012*(xw/lfuse)**2 + 0.538*(xw/lfuse) + 0.0331), TCS([xw >= xcg + dxw]), # Drag D == 0.5*rho*Vinf**2*Sh*CDh, CDh >= CD0h + CLh**2/(pi*e*ARh), # same drag model as vtail CD0h**0.125 >= 0.19*(tau)**0.0075 *(Rec)**0.0017 + 1.83e+04*(tau)**3.54*(Rec)**-0.494 + 0.118*(tau)**0.0082 *(Rec)**0.00165 + 0.198*(tau)**0.00774*(Rec)**0.00168, Rec == rho*Vinf*chma/mu, # Oswald efficiency # Nita, Scholz, # "Estimating the Oswald factor from basic # aircraft geometrical parameters" TCS([fl >= (0.0524*taper**4 - 0.15*taper**3 + 0.1659*taper**2 - 0.0706*taper + 0.0119)], reltol=0.2), # NOTE: slightly slack TCS([e*(1 + fl*ARh) <= 1]), taper >= 0.2, # TODO: make less arbitrary Lmax == 0.5*rho0*Vne**2*Sh*CLhmax, ] standalone_constraints = [M == Vinf/a, ] CG_constraint = [TCS([xcght >= xcg+(dxlead+dxtrail)/2]), xcght <= lfuse ] self.standalone_constraints = standalone_constraints self.CG_constraint = CG_constraint wb = WingBox() wb.subinplace({'A': ARh, 'b': bht, 'L_{max}': Lmax, 'p': p, 'q': q, 'S': Sh, 'taper': taper, r'\tau': tau, 'W_{struct}': W}) lc = LinkedConstraintSet([constraints, wb]) CostedConstraintSet.__init__(self, objective, lc, **kwargs)
def __init__(self, **kwargs): Afan = Variable('A_{fan}', 'm^2', 'Engine reference area') Avt = Variable('A_{vt}', '-', 'Vertical tail aspect ratio') CDvis = Variable('C_{D_{vis}}', '-', 'Viscous drag coefficient') CDwm = Variable('C_{D_{wm}}', '-', 'Windmill drag coefficient') CLvmax = Variable('C_{L_{vmax}}', '-', 'Max lift coefficient') CLvt = Variable('C_{L_{vt}}', '-', 'Vertical tail lift coefficient') Dvt = Variable('D_{vt}', 'N', 'Vertical tail viscous drag, cruise') Dwm = Variable('D_{wm}', 'N', 'Engine out windmill drag') Lmax = Variable('L_{max_{vt}}', 'N', 'Maximum load for structural sizing') # fuselage Lvmax = Variable('L_{v_{max}}', 'N', 'Maximum load for structural sizing') Lvt = Variable('L_{vt}', 'N', 'Vertical tail lift in engine out') Rec = Variable('Re_{vt}', '-', 'Vertical tail reynolds number, cruise') S = Variable('S', 'm^2', 'Vertical tail reference area (full)') Svt = Variable('S_{vt}', 'm^2', 'Vertical tail reference area (half)') Te = Variable('T_e', 'N', 'Thrust per engine at takeoff') V1 = Variable('V_1', 'm/s', 'Minimum takeoff velocity') Vinf = Variable('V_{\\infty}', 'm/s', 'Cruise velocity') Vne = Variable('V_{ne}', 'm/s', 'Never exceed velocity') Wstruct= Variable('W_{struct}', 'N', 'Full span weight') Wvt = Variable('W_{vt}', 'N', 'Vertical tail weight') b = Variable('b', 'm', 'Vertical tail full span') bvt = Variable('b_{vt}', 'm', 'Vertical tail half span') clvt = Variable('c_{l_{vt}}', '-', 'Sectional lift force coefficient (engine out)') cma = Variable('\\bar{c}_{vt}', 'm', 'Vertical tail mean aero chord') croot = Variable('c_{root_{vt}}', 'm', 'Vertical tail root chord') ctip = Variable('c_{tip_{vt}}', 'm', 'Vertical tail tip chord') cvt = Variable('c_{vt}', 'm', 'Vertical tail root chord') # fuselage dfan = Variable('d_{fan}', 'm', 'Fan diameter') dxlead = Variable('\\Delta x_{lead_v}', 'm', 'Distance from CG to vertical tail leading edge') dxtrail= Variable('\\Delta x_{trail_v}', 'm', 'Distance from CG to vertical tail trailing edge') e = Variable('e_v', '-', 'Span efficiency of vertical tail') lfuse = Variable('l_{fuse}', 'm', 'Length of fuselage') lvt = Variable('l_{vt}', 'm', 'Vertical tail moment arm') mu = Variable('\\mu', 'N*s/m^2', 'Dynamic viscosity (35,000 ft)') mu0 = Variable('\\mu_0', 1.8E-5, 'N*s/m^2', 'Dynamic viscosity (SL)') p = Variable('p_{vt}', '-', 'Substituted variable = 1 + 2*taper') plamv = Variable('p_{\\lambda_v}', '-', 'Dummy variable = 1 + 2\\lambda') # fuselage q = Variable('q_{vt}', '-', 'Substituted variable = 1 + taper') rho0 = Variable('\\rho_{TO}', 'kg/m^3', 'Air density (SL))') rho = Variable('\\rho', 'kg/m^3', 'Air density (cruise)') tanL = Variable('\\tan(\\Lambda_{vt})', '-', 'Tangent of leading edge sweep (40 deg)') taper = Variable('\\lambda_{vt}', '-', 'Vertical tail taper ratio') tau = Variable('\\tau_{vt}', '-', 'Vertical tail thickness/chord ratio') xCG = Variable('x_{CG}', 'm', 'x-location of CG') xCGvt = Variable('x_{CG_{vt}}', 'm', 'x-location of tail CG') y_eng = Variable('y_{eng}', 'm', 'Engine moment arm') zmac = Variable('z_{\\bar{c}_{vt}}', 'm', 'Vertical location of mean aerodynamic chord') with SignomialsEnabled(): objective = Dvt + 0.05*Wvt constraints = [ Lvt*lvt >= Te*y_eng + Dwm*y_eng, # Force moment balance for one engine out condition # TASOPT 2.0 p45 TCS([dxlead + zmac*tanL + 0.25*cma >= lvt]), # [SP] # Tail moment arm Lvt == 0.5*rho0*V1**2*Svt*CLvt, # Vertical tail force (y-direction) for engine out Avt == bvt**2/Svt, TCS([CLvt*(1 + clvt/(np.pi*e*Avt)) <= clvt]), # Finite wing theory # people.clarkson.edu/~pmarzocc/AE429/AE-429-4.pdf # Valid because tail is untwisted and uncambered # (lift curve slope passes through origin) Dwm >= 0.5*rho0*V1**2*Afan*CDwm, Afan >= np.pi*(dfan/2)**2, # Drag of a windmilling engine Svt <= bvt*(croot + ctip)/2, # [SP] # Tail geometry relationship TCS([dxtrail >= croot + dxlead]), # Tail geometry constraint lfuse >= dxtrail + xCG, # Fuselage length constrains the tail trailing edge p >= 1 + 2*taper, 2*q >= 1 + p, zmac == (bvt/3)*q/p, TCS([(2./3)*(1 + taper + taper**2)*croot/q >= cma]), # [SP] taper == ctip/croot, # Define vertical tail geometry taper >= 0.27, # TODO: Constrain taper by tip Reynolds number # source: b737.org.uk Dvt >= 0.5*rho*Vinf**2*Svt*CDvis, CDvis**0.125 >= 0.19*(tau)**0.0075 *(Rec)**0.0017 + 1.83e+04*(tau)**3.54*(Rec)**-0.494 + 0.118*(tau)**0.0082 *(Rec)**0.00165 + 0.198*(tau)**0.00774*(Rec)**0.00168, # Vertical tail viscous drag in cruise # Data fit from Xfoil Rec == rho*Vinf*cma/mu, # Cruise Reynolds number S == Svt*2, b == bvt*2, Wvt == Wstruct/2, Lmax == 2*Lvmax, # Relate vertical tail geometry/weight to generic # wing used in structural model Lvmax == 0.5*rho0*Vne**2*Svt*CLvmax, # Max load for structural sizing ] # For linking to other models linking_constraints = [plamv == p, cvt == croot] CG_constraint = [TCS([xCGvt >= xCG+(dxlead+dxtrail)/2], raiseerror=False), xCGvt <= lfuse] self.linking_constraints = linking_constraints self.CG_constraint = CG_constraint # Incorporate the structural model wb = WingBox() wb.subinplace({'b': b, 'L_{max}': Lmax, 'p': p, 'q': q, 'S': S, 'taper': taper, '\\tau': tau}) lc = LinkedConstraintSet([constraints, wb]) CostedConstraintSet.__init__(self, objective, lc)