def __init__(self): Afloor = Variable('A_{floor}', 'm^2', 'Floor beam x-sectional area') Afuse = Variable('A_{fuse}', 'm^2', 'Fuselage x-sectional area') Ahold = Variable('A_{hold}', 'm^2', 'Cargo hold x-sectional area') Askin = Variable('A_{skin}', 'm^2', 'Skin cross sectional area') Dfuse = Variable('D_{fuse}', 'N', 'Total drag in cruise') Dfrict = Variable('D_{friction}', 'N', 'Friction drag') Dupswp = Variable('D_{upsweep}', 'N', 'Drag due to fuse upsweep') FF = Variable('FF', '-','Fuselage form factor') LF = Variable('LF', '-', 'Load factor') Lvmax = Variable('L_{v_{max}}', 'N', 'Max vertical tail load') Mfloor = Variable('M_{floor}', 'N*m', 'Max bending moment in floor beams') Nland = Variable('N_{land}', '-', 'Emergency landing load factor') Pfloor = Variable('P_{floor}', 'N', 'Distributed floor load') Qv = Variable('Q_v', 'N*m', 'Torsion moment imparted by tail') R = Variable('R', 287, 'J/(kg*K)', 'Universal gas constant') Rfuse = Variable('R_{fuse}', 'm', 'Fuselage radius') SPR = Variable('SPR', '-', 'Number of seats per row') Sbulk = Variable('S_{bulk}', 'm^2', 'Bulkhead surface area') Sfloor = Variable('S_{floor}', 'N', 'Maximum shear in floor beams') Snose = Variable('S_{nose}', 'm^2', 'Nose surface area') Tcabin = Variable('T_{cabin}', 'K', 'Cabin temperature') Vbulk = Variable('V_{bulk}', 'm^3', 'Bulkhead skin volume') Vcabin = Variable('V_{cabin}', 'm^3', 'Cabin volume') Vcargo = Variable('V_{cargo}', 'm^3', 'Cargo volume') Vcone = Variable('V_{cone}', 'm^3', 'Cone skin volume') Vcyl = Variable('V_{cyl}', 'm^3', 'Cylinder skin volume') Vfloor = Variable('V_{floor}', 'm^3', 'Floor volume') Vhold = Variable('V_{hold}', 'm^3', 'Hold volume') Vinf = Variable('V_{\\infty}', 'm/s', 'Cruise velocity') Vlugg = Variable('V_{lugg}', 'm^3', 'Luggage volume') Vnose = Variable('V_{nose}', 'm^3', 'Nose skin volume') Wapu = Variable('W_{apu}', 'N', 'APU weight') Wavgpass = Variable('W_{avg. pass}', 'lbf', 'Average passenger weight') Wbuoy = Variable('W_{buoy}', 'N', 'Buoyancy weight') Wcargo = Variable('W_{cargo}', 'N', 'Cargo weight') Wcarryon = Variable('W_{carry on}', 'lbf', 'Ave. carry-on weight') Wchecked = Variable('W_{checked}', 'lbf', 'Ave. checked bag weight') Wcone = Variable('W_{cone}', 'N', 'Cone weight') Wfix = Variable('W_{fix}', 'lbf', 'Fixed weights (pilots, cockpit seats, navcom)') Wfloor = Variable('W_{floor}', 'N', 'Floor weight') Wfuse = Variable('W_{fuse}', 'N', 'Fuselage weight') Winsul = Variable('W_{insul}', 'N', 'Insulation material weight') Wlugg = Variable('W_{lugg}', 'N', 'Passenger luggage weight') Wpadd = Variable('W_{padd}', 'N', 'Misc weights (galley, toilets, doors etc.)') Wpass = Variable('W_{pass}', 'N', 'Passenger weight') Wpay = Variable('W_{pay}', 'N', 'Payload weight') Wppfloor = Variable('W\'\'_{floor}', 'N/m^2', 'Floor weight/area density') Wppinsul = Variable('W\'\'_{insul}', 'N/m^2', 'Weight/area density of insulation material') Wpseat = Variable('W\'_{seat}', 'N', 'Weight per seat') Wpwindow = Variable('W\'_{window}', 'N/m', 'Weight/length density of windows') Wseat = Variable('W_{seat}', 'N', 'Seating weight') Wshell = Variable('W_{shell}', 'N', 'Shell weight') Wskin = Variable('W_{skin}', 'N', 'Skin weight') Wwindow = Variable('W_{window}', 'N', 'Window weight') bvt = Variable('b_{vt}', 'm', 'Vertical tail span') cvt = Variable('c_{vt}', 'm', 'Vertical tail root chord') dh = Variable('\\Delta h', 'm', 'Distance from floor to widest part of fuselage') dp = Variable('\\Delta p', 'Pa', 'Pressure difference across fuselage skin') f = Variable('f', '-', 'Fineness ratio') fapu = Variable('f_{apu}', '-', 'APU weight as fraction of payload weight') ffadd = Variable('f_{fadd}', '-', 'Fractional added weight of local reinforcements') fframe = Variable('f_{frame}', '-', 'Fractional frame weight') flugg1 = Variable('f_{lugg,1}', '-', 'Proportion of passengers with one suitcase') flugg2 = Variable('f_{lugg,2}', '-', 'Proportion of passengers with two suitcases') fpadd = Variable('f_{padd}', '-', 'Other misc weight as fraction of payload weight') fstring = Variable('f_{string}', '-','Fractional weight of stringers') g = Variable('g', 9.81, 'm/s^2', 'Gravitational acceleration') hfloor = Variable('h_{floor}', 'm', 'Floor beam height') hhold = Variable('h_{hold}', 'm', 'Height of the cargo hold') lamcone = Variable('\\lambda_{cone}', '-', 'Tailcone radius taper ratio (xshell2->xtail)') lcone = Variable('l_{cone}', 'm', 'Cone length') lfloor = Variable('l_{floor}', 'm', 'Floor length') lfuse = Variable('l_{fuse}', 'm', 'Fuselage length') lnose = Variable('l_{nose}', 'm', 'Nose length') lshell = Variable('l_{shell}', 'm', 'Shell length') mu = Variable('\\mu', 'N*s/m^2', 'Dynamic viscosity (35,000 ft)') npass = Variable('n_{pass}', '-', 'Number of passengers') nrows = Variable('n_{rows}', '-', 'Number of rows') nseat = Variable('n_{seat}', '-',' Number of seats') pcabin = Variable('p_{cabin}', 'Pa','Cabin air pressure (8,000ft)') phi = Variable('\\phi', '-', 'Upsweep angle') pitch = Variable('p_s', 'in', 'Seat pitch') plamv = Variable('p_{\\lambda_v}', '-', '1 + 2*Tail taper ratio') rE = Variable('r_E', '-', 'Ratio of stringer/skin moduli') rho = Variable('\\rho', 'kg/m^3', 'Air density (cruise)') rhobend = Variable('\\rho_{bend}', 'kg/m^3', 'Stringer density') rhocabin = Variable('\\rho_{cabin}', 'kg/m^3', 'Air density in cabin') rhocargo = Variable('\\rho_{cargo}', 'kg/m^3', 'Cargo density') rhocone = Variable('\\rho_{cone}', 'kg/m^3', 'Cone material density') rhofloor = Variable('\\rho_{floor}', 'kg/m^3', 'Floor material density') rholugg = Variable('\\rho_{lugg}', 'kg/m^3', 'Luggage density') rhoskin = Variable('\\rho_{skin}', 'kg/m^3', 'Skin density') sigfloor = Variable('\\sigma_{floor}', 'N/m^2', 'Max allowable cap stress') sigskin = Variable('\\sigma_{skin}', 'N/m^2', 'Max allowable skin stress') sigth = Variable('\\sigma_{\\theta}', 'N/m^2', 'Skin hoop stress') sigx = Variable('\\sigma_x', 'N/m^2', 'Axial stress in skin') taucone = Variable('\\tau_{cone}', 'N/m^2', 'Shear stress in cone') taufloor = Variable('\\tau_{floor}', 'N/m^2', 'Max allowable shear web stress') tcone = Variable('t_{cone}', 'm', 'Cone thickness') tshell = Variable('t_{shell}', 'm', 'Shell thickness') tskin = Variable('t_{skin}', 'm', 'Skin thickness') waisle = Variable('w_{aisle}', 'm', 'Aisle width') wfloor = Variable('w_{floor}', 'm', 'Floor width') wfuse = Variable('w_{fuse}', 'm', 'Fuselage width') wseat = Variable('w_{seat}', 'm', 'Seat width') wsys = Variable('w_{sys}', 'm', 'Width between cabin and skin for systems') xCGfu = Variable('x_{CG_{fu}}', 'm', 'x-location of fuselage CG') xVbulk = Variable('xVbulk', 'm^4', 'Volume moment of bulkhead') xVcyl = Variable('xVcyl', 'm^4', 'Volume moment of cylinder') xVnose = Variable('xVnose', 'm^4', 'Volume moment of nose') xWapu = Variable('xWapu', 'N*m', 'Moment of APU') xWcone = Variable('xWcone', 'N*m', 'Moment of cone') xWfix = Variable('xWfix', 'N*m', 'Moment of fixed weights') xWfloor = Variable('xWfloor', 'N*m', 'Moment of floor weight') xWfuse = Variable('xWfuse', 'N*m', 'Fuselage moment') xWinsul = Variable('xWinsul', 'N*m', 'Moment of insulation material') xWpadd = Variable('xWpadd', 'N*m', 'Moment of misc weights') xWseat = Variable('xWseat', 'N*m', 'Moment of seats') xWshell = Variable('xWshell', 'N*m', 'Mass moment of shell') xWskin = Variable('xWskin', 'N*m', 'Mass moment of skin') xWwindow = Variable('xWwindow', 'N*m', 'Mass moment of windows') x_upswp = Variable('x_{up}', 'm', 'Fuselage upsweep point') xapu = Variable('xapu', 'ft', 'x-location of APU') xconend = Variable('xconend', 'm', 'x-location of cone end') xfix = Variable('xfix', 'm', 'x-location of fixed weight') xshell1 = Variable('x_{shell1}', 'm', 'Start of cylinder section') xshell2 = Variable('x_{shell2}', 'm', 'End of cylinder section') with SignomialsEnabled(): objective = Dfuse + 0.5*Wfuse constraints = [ # Geometry relations lnose == xshell1, # Cross section relations wfuse == 2*Rfuse, wfuse >= SPR*wseat + waisle + 2*wsys, Askin >= 2*np.pi*Rfuse*tskin, # simplified Afuse >= np.pi*Rfuse**2, # simplified tshell >= tskin*(1 + rE*fstring*rhoskin/rhobend), # TODO: Bending loads # Pressure shell loads sigx == dp/2*Rfuse/tshell, sigth == dp*Rfuse/tskin, sigskin >= sigth, sigskin >= sigx, Snose**(8./5) >= (2*np.pi*Rfuse**2)**(8./5) * (1./3 + (2./3)*(lnose/Rfuse) **(8./5)), Sbulk == 2*np.pi*Rfuse**2, Vcyl == Askin*lshell, Vnose == Snose*tskin, Vbulk == Sbulk*tskin, Wskin >= rhoskin*g*(Vcyl + Vnose + Vbulk), Wshell >= Wskin*(1 + fstring + fframe + ffadd), # Cabin volume and buoyancy weight rhocabin == (1/(R*Tcabin))*pcabin, Vcabin >= Afuse*(lshell + 0.67*lnose + 0.67*Rfuse), TCS([Wbuoy >= (rhocabin - rho)*g*Vcabin], reltol=1E-3), # [SP] # Windows and insulation Wwindow == Wpwindow * lshell, Winsul >= Wppinsul*(1.1*np.pi*Rfuse*lshell + 0.55*(Snose + Sbulk)), # Payload-proportional weights Wapu == Wpay*fapu, Wseat == Wpseat*nseat, Wpadd == Wpay*fpadd, # Floor Pfloor >= Nland*(Wpay + Wseat), Sfloor == 0.5*Pfloor, # without support Mfloor == 0.25*Pfloor*wfloor/2, lnose >= 5.2*units.m, # TODO less arbitrary Afloor >= 2*Mfloor/(sigfloor*hfloor) + 1.5*Sfloor/taufloor, Vfloor >= wfloor*Afloor, lfloor >= lshell + 2*Rfuse, lshell >= nrows*pitch, (wfloor/2)**2 + dh**2 >= Rfuse**2, # [SP] Wfloor >= rhofloor*g*Vfloor + wfloor*lfloor*Wppfloor, # Tail cone Rfuse*taucone*(1+plamv)*Vcone*(1+lamcone)/(4*lcone) >= Lvmax*bvt*plamv/3, # [SP] plamv >= 1.6, taucone == sigskin, lamcone == 0.4, # TODO remove lamcone == cvt/lcone, Wcone >= rhocone*g*Vcone*(1 + fstring + fframe + ffadd), # Payload weight breakdown npass == nseat*LF, nseat == nrows*SPR, Wpass == npass*Wavgpass, Wlugg >= flugg2*npass*2*Wchecked + flugg1*npass*Wchecked + Wcarryon, Wlugg == Vlugg*g*rholugg, Wcargo == Vcargo*g*rhocargo, Vhold >= Vcargo + Vlugg, Vhold == Ahold*lshell, TCS([Ahold <= (2./3)*wfloor*hhold + hhold**3/(2*wfloor)], reltol=1E-5), # [SP] Harris stocker 1998 (wolfram) TCS([dh + hhold + hfloor <= Rfuse]), Wpay >= Wpass + Wlugg + Wcargo, # Total fuselage weight Wfuse >= Wfix + Wapu + Wpadd + Wseat + Wshell + Wwindow + Winsul + Wcone + Wfloor + Wbuoy, # Drag # sources: Raymer (p285), kfid 325 notes (p180) lfuse >= lnose+lshell+lcone, f == lfuse/((4/np.pi*Afuse)**0.5), # fineness ratio FF >= 1 + 60/f**3 + f/400, # form factor Dfrict >= FF * np.pi*Rfuse * mu*Vinf * 0.074*(rho*Vinf*lfuse/mu)**0.8, # Drag due to fuselage upsweep (Raymer p286) xshell2 >= xshell1 + lshell, xshell2 == x_upswp, x_upswp + lcone <= lfuse, 1.13226*phi**1.03759 == Rfuse/lcone, # monomial fit # of tan(phi) Dupswp >= 3.83*phi**2.5*Afuse * 0.5*rho*Vinf**2, Dfuse >= Dfrict + Dupswp ] CG_constraints = [ xVcyl >= 0.5*(xshell1+xshell2)*Vcyl, xVnose >= 0.5*(xshell1)*Vnose, xVbulk >= xshell2*Vbulk, # simplified xWskin >= rhoskin*g*(xVcyl + xVnose + xVbulk), xWshell >= xWskin*(1 + fstring + fframe + ffadd), xWwindow >= 0.5* (xshell1+xshell2)*Wwindow, xWinsul >= 0.5*(xshell1 + xshell2)*Winsul, xWapu == xapu*Wapu, xWseat >= 0.5*(xshell1 + xshell2)*Wseat, xWpadd >= 0.5*(xshell1 + xshell2)*Wpadd, xWfix == xfix*Wfix, xWfloor >= 0.5*(xshell1 + xshell2)*Wfloor, xWcone >= 0.5*(xshell2 + lfuse) * Wcone, xWfuse >= xWfix + xWapu + xWpadd + xWseat + xWshell + xWcone + xWwindow + xWinsul + xWfloor, xCGfu == xWfuse/Wfuse, ] self.CG_constraints = CG_constraints CostedConstraintSet.__init__(self, objective, constraints)
def __init__(self): B = Variable('B', 'm', 'Landing gear base') E = Variable('E', 'GPa', 'Modulus of elasticity, 4340 steel') Eland = Variable('E_{land}', 'J', 'Max KE to be absorbed in landing') Fwm = Variable('F_{w_m}', '-', 'Weight factor (main)') Fwn = Variable('F_{w_n}', '-', 'Weight factor (nose)') I_m = Variable('I_m', 'm^4', 'Area moment of inertia (main strut)') I_n = Variable('I_n', 'm^4', 'Area moment of inertia (nose strut)') K = Variable('K', '-', 'Column effective length factor') L_m = Variable('L_m', 'N', 'Max static load through main gear') L_n = Variable('L_n', 'N', 'Min static load through nose gear') L_n_dyn = Variable('L_{n_{dyn}}', 'N', 'Dyn. braking load, nose gear') Lwm = Variable('L_{w_m}', 'N', 'Static load per wheel (main)') Lwn = Variable('L_{w_n}', 'N', 'Static load per wheel (nose)') N_s = Variable('N_s', '-', 'Factor of safety') S_sa = Variable('S_{sa}', 'm', 'Stroke of the shock absorber') S_t = Variable('S_t', 'm', 'Tire deflection') T = Variable('T', 'm', 'Main landing gear track') W = Variable('W', 'N', 'Total aircraft weight') WAWm = Variable('W_{wa,m}', 'lbf', 'Wheel assembly weight for single main gear wheel') WAWn = Variable('W_{wa,n}', 'lbf', 'Wheel assembly weight for single nose gear wheel') W_0 = Variable('W_{0_{lg}}', 'N', 'Weight of aircraft excluding landing gear') W_lg = Variable('W_{lg}', 'N', 'Weight of landing gear') W_mg = Variable('W_{mg}', 'N', 'Weight of main gear') W_ms = Variable('W_{ms}', 'N', 'Weight of main struts') W_mw = Variable('W_{mw}', 'N', 'Weight of main wheels (per strut)') W_ng = Variable('W_{ng}', 'N', 'Weight of nose gear') W_ns = Variable('W_{ns}', 'N', 'Weight of nose strut') W_nw = Variable('W_{nw}', 'N', 'Weight of nose wheels (total)') d_fan = Variable('d_{fan}', 'm', 'Fan diameter') d_nac = Variable('d_{nacelle}', 'm', 'Nacelle diameter') d_oleo = Variable('d_{oleo}', 'm', 'Diameter of oleo shock absorber') dtm = Variable('d_{t_m}', 'in', 'Diameter of main gear tires') dtn = Variable('d_{t_n}', 'in', 'Diameter of nose gear tires') dxm = Variable('\\Delta x_m', 'm', 'Distance b/w main gear and CG') dxn = Variable('\\Delta x_n', 'm', 'Distance b/w nose gear and CG') eta_s = Variable('\\eta_s', '-', 'Shock absorber efficiency') faddm = Variable('f_{add,m}', '-', 'Proportional added weight, main') faddn = Variable('f_{add,n}', '-', 'Proportional added weight, nose') g = Variable('g', 9.81, 'm/s^2', 'Gravitational acceleration') h_nac = Variable('h_{nacelle}', 'm', 'Min. nacelle clearance') hhold = Variable('h_{hold}', 'm', 'Hold height') l_m = Variable('l_m', 'm', 'Length of main gear') l_n = Variable('l_n', 'm', 'Length of nose gear') l_oleo = Variable('l_{oleo}', 'm', 'Length of oleo shock absorber') lam = Variable('\\lambda_{LG}', '-', 'Ratio of max to static load') # Torenbeek p360 n_mg = Variable('n_{mg}', '-', 'Number of main gear struts') nwps = Variable('n_{wps}', '-', 'Number of wheels per strut') p_oleo = Variable('p_{oleo}', 'lbf/in^2', 'Oleo pressure') #p_t = Variable('p_t', 170, 'lbf/in^2', 'Tyre pressure') r_m = Variable('r_m', 'm', 'Radius of main gear struts') r_n = Variable('r_n', 'm', 'Radius of nose gear struts') rho_st = Variable('\\rho_{st}', 'kg/m^3', 'Density of 4340 Steel') sig_y_c = Variable('\\sigma_{y_c}', 'Pa', 'Compressive yield strength 4340 steel') # AZOM t_m = Variable('t_m', 'm', 'Thickness of main gear strut wall') t_n = Variable('t_n', 'm', 'Thickness of nose gear strut wall') t_nac = Variable('t_{nacelle}', 'm', 'Nacelle thickness') tan_15 = Variable('\\tan(\\phi_{min})', '-', 'Lower bound on phi') tan_63 = Variable('\\tan(\\psi_{max})', '-', 'Upper bound on psi') tan_gam = Variable('\\tan(\\gamma)', '-', 'Dihedral angle') tan_phi = Variable('\\tan(\\phi)', '-', 'Angle b/w main gear and CG') tan_psi = Variable('\\tan(\\psi)', '-', 'Tip over angle') tan_th = Variable('\\tan(\\theta_{max})', '-', 'Max rotation angle') w_ult = Variable('w_{ult}', 'ft/s', 'Ultimate velocity of descent') wtm = Variable('w_{t_m}', 'm', 'Width of main tires') wtn = Variable('w_{t_n}', 'm', 'Width of nose tires') x_m = Variable('x_m', 'm', 'x-location of main gear') x_n = Variable('x_n', 'm', 'x-location of nose gear') x_upswp = Variable('x_{up}', 'm', 'Fuselage upsweep point') xcg = Variable('x_{CG}', 'm', 'x-location of CG incl. LG') xcglg = Variable('x_{CG_{lg}}', 'm', 'Landing gear CG') xcg0 = Variable('x_{CG_0}', 'm', 'x-location of CG excl. LG') y_eng = Variable('y_{eng}', 'm', 'Spanwise loc. of engines') y_m = Variable('y_m', 'm', 'y-location of main gear (symmetric)') z_CG_0 = Variable('z_{CG}', 'm', 'CG height relative to bottom of fuselage') zwing = Variable('z_{wing}', 'm', 'Height of wing relative to base of fuselage') with SignomialsEnabled(): objective = W_lg constraints = [ # Track and Base geometry definitions TCS([l_n+zwing+y_m*tan_gam>=l_m], reltol=1E-3), #[SP] T == 2*y_m, TCS([x_n + B <= x_m]), x_n >= 5*units.m, # nose gear after nose # Geometric constraints relating gear placement with # fore/aft CG locations TCS([dxn + x_n >= xcg], reltol=1E-3), # [SP] TCS([dxm + xcg >= x_m], reltol=1E-4), # [SP] # TODO forward and aft CG # Maximum static loads through main and nose gears L_n == W*dxm/B, L_m == W*dxn/B, # Dynamic braking load through nose gear # (assumes deceleration of 10 ft/s^2) L_n_dyn >= 0.31*((z_CG_0+l_m)/B)*W, # For steering don't want too much or too little # load on nose gear L_n/W >= 0.05, L_n/W <= 0.20, # Longitudinal tip over (static) x_m >= tan_phi*(z_CG_0+l_m) + xcg, tan_phi >= tan_15, # Lateral tip over in turn (dynamic) # www.dept.aoe.vt.edu/~mason/Mason_f/M96SC03.pdf # stricter constraint uses forward CG # cos(arctan(y/x))) = x/sqrt(x^2 + y^2) 1 >= (z_CG_0 + l_m)**2 * (y_m**2 + B**2) / (dxn * y_m * tan_psi)**2, tan_psi <= tan_63, # Tail strike: Longitudinal ground clearance in # takeoff, landing (Raymer says 10-15 degrees) # TODO?: 2 cases:(i) upsweep angle > rotation angle, # (ii) upsweep angle < rotation ang x_upswp - x_m <= l_m/tan_th, # [SP] # Engine ground clearance d_nac >= d_fan + 2*t_nac, d_nac + h_nac <= l_m + (y_eng-y_m)*tan_gam, # [SP] # Size/Volume for retraction y_m >= l_m, # Constrains/is constrained by engine location y_m <= y_eng, # Brake sizing for stopping aircraft # Hard landing # http://www.boeing.com/commercial/aeromagazine/... # articles/qtr_3_07/AERO_Q307_article3.pdf # sink rate of 10 feet per second at the maximum # design landing weight # Landing condition from Torenbeek p360 Eland >= W/(2*g)*w_ult**2, # Torenbeek (10-26) # S_t == 0.5*lam*Lwm/(p*(dtm*bt)**0.5), # (10-30) S_sa == (1/eta_s)*(Eland/(L_m*lam)),# - eta_t*S_t), # [SP] Torenbeek (10-28) l_oleo == 2.5*S_sa, # Raymer 244 d_oleo == 1.3*(4*lam*L_m/n_mg/(np.pi*p_oleo))**0.5, l_m >= l_oleo + dtm/2, # Wheel weights Fwm == Lwm*dtm/(1000*Lwm.units*dtm.units), WAWm == 1.2*Fwm**0.609*units.lbf,# Currey p145 Fwn == Lwn*dtn/(1000*units.lbf*units.inches), WAWn == 1.2*Fwn**0.609*units.lbf,# Currey p145 Lwm == L_m/(n_mg*nwps), Lwn == L_n/nwps, # Main wheel diameter/width (Raymer p233) dtm == 1.63*(Lwm/(4.44*units.N))**0.315*units.inch, wtm == 0.1043*(Lwm/(4.44*units.N))**0.48*units.inch, dtn == 0.8*dtm, wtn == 0.8*wtm, # TODO: Beam sizing and max bending (limits track, # downward pressure on y_m) # Weight is a function of height and load through # each strut as well as tyre size (and obviously # number of struts) # Main gear strut weight (for a single strut) is a # function of length and load passing through strut W_ms >= 2*np.pi*r_m*t_m*l_m * rho_st * g, # Compressive yield in hard landing condition N_s * lam * L_m/n_mg <= sig_y_c * (2*np.pi*r_m*t_m), W_mw == nwps*WAWm, # Nose gear strut weight is a function of length and # load passing through strut W_ns >= 2*np.pi*r_n*t_n*l_n * rho_st * g, # find cross sectional area based on compressive yield N_s * (L_n + L_n_dyn) <= sig_y_c*(2*np.pi*r_n*t_n), W_nw >= nwps*WAWn, # Buckling constraint on main gear L_m <= np.pi**2*E*I_m/(K*l_m)**2, I_m == np.pi*r_m**3*t_m, # Buckling constraint on nose gear # source: https://en.wikipedia.org/wiki/Buckling L_n <= np.pi**2*E*I_n/(K*l_n)**2, I_n == np.pi*r_n**3*t_n, # Machining constraint # p89 Mason # www.dept.aoe.vt.edu/~mason/Mason_f/M96SC08.pdf 2*r_m/t_m <= 40, 2*r_m/t_n <= 40, # Retraction constraint on strut diameter 2*wtm + 2*r_m <= hhold, 2*wtn + 2*r_n <= 0.8*units.m, #TODO improve this # Weight accounting W_mg >= n_mg*(W_ms + W_mw*(1 + faddm)),# Currey p264 W_ng >= W_ns + W_nw*(1 + faddn), W_lg >= W_mg + W_ng, ] standaloneCG = [ # CG location affected by landing gear position TCS([xcg*W <= W_0*xcg0 + W_ng*x_n + W_mg*x_m]), W >= W_0 + W_lg, ] coupledCG = [ TCS([W_lg*xcglg >= W_ng*x_n + W_mg*x_m], reltol=1E-2, raiseerror=False), x_m >= xcglg, ] self.standaloneCG = standaloneCG self.coupledCG = coupledCG CostedConstraintSet.__init__(self, objective, constraints)
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): 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 test_vector_cost(self): x = VectorVariable(2, "x") self.assertRaises(ValueError, CostedConstraintSet, x, []) _ = CostedConstraintSet(np.array(x[0]), [])
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)