def setup(self, alt, **kwargs): g = Variable('g', 'm/s^2', 'Gravitational acceleration') p_sl = Variable("p_{sl}", 101325, "Pa", "Pressure at sea level") T_sl = Variable("T_{sl}", 288.15, "K", "Temperature at sea level") L_atm = Variable("L_{atm}", .0065, "K/m", "Temperature lapse rate") M_atm = Variable("M_{atm}", .0289644, "kg/mol", "Molar mass of dry air") p_atm = Variable("P_{atm}", "Pa", "air pressure") R_atm = Variable("R_{atm}", 8.31447, "J/mol/K", "air specific heating value") TH = 5.257386998354459 #(g*M_atm/R_atm/L_atm).value rho = Variable('\\rho', 'kg/m^3', 'Density of air') T_atm = Variable("T_{atm}", "K", "air temperature") """ Dynamic viscosity (mu) as a function of temperature References: http://www-mdp.eng.cam.ac.uk/web/library/enginfo/aerothermal_dvd_only/aero/ atmos/atmos.html http://www.cfd-online.com/Wiki/Sutherland's_law """ mu = Variable('\\mu', 'kg/(m*s)', 'Dynamic viscosity') T_s = Variable('T_s', 110.4, "K", "Sutherland Temperature") C_1 = Variable('C_1', 1.458E-6, "kg/(m*s*K^0.5)", 'Sutherland coefficient') with SignomialsEnabled(): constraints = [ # Pressure-altitude relation (p_atm/p_sl)**(1/5.257) == T_atm/T_sl, # Ideal gas law rho == p_atm/(R_atm/M_atm*T_atm), #temperature equation SignomialEquality(T_sl, T_atm + L_atm*alt['h']), #constraint on mu SignomialEquality((T_atm + T_s) * mu, C_1 * T_atm**1.5), ## TCS([(T_atm + T_s) * mu >= C_1 * T_atm**1.5]) ] #like to use a local subs here in the future subs = None return constraints
def setup(self, **kwargs): #declare variables #Variables Afuel = Variable('\\bar{A}_{fuel, max}', '-', 'Non-dim. fuel area') CLwmax = Variable('C_{L_{w,max}}', '-', 'Max lift coefficient, wing') Vfuel = Variable('V_{fuel, max}', 'm^3', 'Available fuel volume') 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') eta = Variable('\\eta', '-', 'Lift efficiency (diff b/w sectional, actual lift)') fl = Variable('f(\\lambda_w)', '-', 'Empirical efficiency function of taper') g = Variable('g', 9.81, 'm/s^2', 'Gravitational acceleration') p = Variable('p', '-', 'Substituted variable = 1 + 2*taper') q = Variable('q', '-', 'Substituted variable = 1 + taper') rho0 = Variable('\\rho_0', 1.225, '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', '-', 'Wing thickness/chord ratio') tau_max = Variable('\\tau_{max_w}', '-', 'Max allowed wing thickness') wwn = Variable('wwn', 0.5, '-', 'Wingbox-width-to-chord ratio') xw = Variable('x_w', 'm', 'Position of wing aerodynamic center') ymac = Variable('y_{mac}', 'm', 'Spanwise location of mean aerodynamic chord') bmax = Variable('b_{max}', 'm', 'Max Wing Span') #Linked Variables AR = Variable('AR', '-', 'Wing aspect ratio') Lmax = Variable('L_{max}', 'N', 'Maximum load') Sw = Variable('S', 'm^2', 'Wing area') WfuelWing = Variable('W_{fuel_{wing}}', 'N', 'Fuel weight') b = Variable('b', 'm', 'Wing span') mac = Variable('mac', 'm', 'Mean aerodynamic chord (wing)') e = Variable('e', '-', 'Oswald efficiency factor') FuelFrac = Variable('FuelFrac', '-', 'Usability Factor of Max Fuel Volume') #fractional componenet weights fflap = Variable('f_{flap}', '-', 'Flap Fractional Weight') fslat = Variable('f_{slat}', '-', 'Slat Fractional Weight') faile = Variable('f_{aileron}', '-', 'Aileron Fractional Weight') flete = Variable('f_{lete}', '-', 'Lete Fractional Weight') fribs = Variable('f_{ribs}', '-', 'Rib Fractional Weight') fspoi = Variable('f_{spoiler}', '-', 'Spoiler Fractional Weight') fwatt = Variable('f_{watt}', '-', 'Watt Fractional Weight') # Area fractions Atri = Variable('A_{tri}','m^2','Triangular Wing Area') Arect = Variable('A_{rect}','m^2','Rectangular Wing Area') #make constraints constraints = [] with SignomialsEnabled(): constraints.extend([ Arect == ctip*b, Atri >= 1./2.*(1-taper)*croot*b, #[SP] p >= 1 + 2*taper, 2*q >= 1 + p, ymac == (b/3)*q/p, TCS([(2./3)*(1+taper+taper**2)*croot/q <= mac], reltol=1E-2), taper == ctip/croot, SignomialEquality(Sw, b*(croot + ctip)/2), # 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.15, # TODO # Fuel volume [TASOPT doc] # GP approx of the signomial constraint: Vfuel <= .3026*mac**2*b*tau, WfuelWing <= rhofuel*Vfuel*g, b <= bmax, ]) return constraints
def setup(self, wing, state, **kwargs): self.wing = wing #declare variables #Vector Variables alpha = Variable('\\alpha_w', '-', 'Wing angle of attack') CLaw = Variable('C_{L_{\\alpha,w}}', '-', 'Lift curve slope, wing') Re = Variable('Re_w', '-', 'Reynolds number (wing)') CDp = Variable('C_{D_{p_w}}', '-', 'Wing parasitic drag coefficient') CDi = Variable('C_{D_{i_w}}', '-', 'Wing induced drag coefficient') CDw = Variable('C_{d_w}', '-', 'Drag coefficient, wing') CLw = Variable('C_{L}', '-', 'Lift coefficient, wing') D = Variable('D_{wing}', 'N', 'Wing drag') Lw = Variable('L_w', 'N', 'Wing lift') # Center wing section lift reduction variables dLo = Variable('\\Delta L_{o}','N','Center wing lift loss') etao = Variable('\\eta_{o}','-','Center wing span coefficient') po = Variable('p_{o}','N/m','Center section theoretical wing loading') fLo = Variable('f_{L_{o}}',0.5,'-','Center wing lift reduction coefficient') # Wing tip lift reduction variables dLt = Variable('\\Delta L_{t}','N','Wing tip lift loss') fLt = Variable('f_{L_{t}}',0.05,'-','Wing tip lift reduction coefficient') #wing moment variables -- need a good way to model this, currently using TAT cmw = Variable('c_{m_{w}}', '-', 'Wing Pitching Moment Coefficient') amax = Variable('\\alpha_{max,w}', '-', 'Max angle of attack') #make constraints constraints = [] with SignomialsEnabled(): constraints.extend([ 0.5*state['\\rho']*state['V']**2*self.wing['S']*CLw >= Lw + dLo + 2.*dLt, dLo == etao*fLo*self.wing['b']/2*po, dLt == fLt*po*self.wing['c_{root}']*self.wing['taper']**2, # TODO improve approximations croot~co and taper~gammat # DATCOM formula (Mach number makes it SP) # Swept wing lift curve slope constraint SignomialEquality((self.wing['AR']/self.wing['\\eta'])**2*(1 + self.wing['\\tan(\\Lambda)']**2 - state['M']**2) + 8*pi*self.wing['AR']/CLaw , (2*pi*self.wing['AR']/CLaw)**2), CLw == CLaw*alpha, alpha <= amax, # Drag D == 0.5*state['\\rho']*state['V']**2*self.wing['S']*CDw, TCS([CDw >= CDp + CDi]), TCS([CDi >= self.wing['TipReduct']*CLw**2/(pi*(self.wing['e'])*self.wing['AR'])]), Re == state['\\rho']*state['V']*self.wing['mac']/state['\\mu'], #original Philippe thesis fit ## TCS([CDp**6.5 >= (1.02458748e10 * CLw**15.587947404823325 * (self.wing['\\cos(\\Lambda)']*state['M'])**156.86410659495155 + ## 2.85612227e-13 * CLw**1.2774976672501526 * (self.wing['\\cos(\\Lambda)']*state['M'])**6.2534328002723703 + ## 2.08095341e-14 * CLw**0.8825277088649582 * (self.wing['\\cos(\\Lambda)']*state['M'])**0.0273667615730107 + ## 1.94411925e+06 * CLw**5.6547413360261691 * (self.wing['\\cos(\\Lambda)']*state['M'])**146.51920742858428)]), ## ]) #Martin's TASOPT c series airfoil fit TCS([ CDp**1.6515 >= 1.61418 * (Re/1000)**-0.550434 * (self.wing['\\tau'])**1.29151 * (self.wing['\\cos(\\Lambda)']*state['M'])**3.03609 * CLw**1.77743 + 0.0466407 * (Re/1000)**-0.389048 * (self.wing['\\tau'])**0.784123 * (self.wing['\\cos(\\Lambda)']*state['M'])**-0.340157 * CLw**0.950763 + 190.811 * (Re/1000)**-0.218621 * (self.wing['\\tau'])**3.94654 * (self.wing['\\cos(\\Lambda)']*state['M'])**19.2524 * CLw**1.15233 + 2.82283e-12 * (Re/1000)**1.18147 * (self.wing['\\tau'])**-1.75664 * (self.wing['\\cos(\\Lambda)']*state['M'])**0.10563 * CLw**-1.44114 ]), ]) return constraints
def setup(self, **kwargs): #define new variables Avt = Variable('A_{vt}', '-', 'Vertical tail aspect ratio') CDwm = Variable('C_{D_{wm}}', '-', 'Windmill drag coefficient') Dwm = Variable('D_{wm}', 'N', 'Engine out windmill drag') Lvmax = Variable('L_{vt_{max}}', 'N', 'Maximum load for structural sizing') CLvmax = Variable('C_{L_{vt,max}}', '-', 'Max lift coefficient') CLvtEO = Variable('C_{L_{vt,EO}}', '-', 'Vertical tail lift coefficient (engine out)') clvtEO = Variable('c_{l_{vt,EO}}', '-', 'Sectional lift force coefficient (engine out)') LvtEO = Variable('L_{vt,EO}', 'N', 'Vertical tail lift in engine out') Svt = Variable('S_{vt}', 'm^2', 'Vertical tail reference area') V1 = Variable('V_1', 'm/s', 'Minimum takeoff velocity') bvt = Variable('b_{vt}', 'm', 'Vertical tail span') 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') e = Variable('e_{vt}', '-', 'Span efficiency of vertical tail') dxlead = Variable('\\Delta x_{lead_{vt}}', 'm', 'Distance from CG to vertical tail leading edge') dxtrail = Variable('\\Delta x_{trail_{vt}}', 'm', 'Distance from CG to vertical tail trailing edge') lvt = Variable('l_{vt}', 'm', 'Vertical tail moment arm') mu0 = Variable('\\mu_0', 1.8E-5, 'N*s/m^2', 'Dynamic viscosity (SL)') p = Variable('p_{vt}', '-', 'Substituted variable = 1 + 2*taper') q = Variable('q_{vt}', '-', 'Substituted variable = 1 + taper') rho0 = Variable('\\rho_{TO}', 'kg/m^3', 'Air density (SL))') tanL = Variable('\\tan(\\Lambda_{vt})', '-', 'Tangent of leading edge sweep') taper = Variable('\\lambda_{vt}', '-', 'Vertical tail taper ratio') tau = Variable('\\tau_{vt}', '-', 'Vertical tail thickness/chord ratio') xCGvt = Variable('x_{CG_{vt}}', 'm', 'x-location of tail CG') y_eng = Variable('y_{eng}', 'm', 'Engine moment arm') ymac = Variable('y_{\\bar{c}_{vt}}', 'm', 'Spanwise location of mean aerodynamic chord') zmac = Variable('z_{\\bar{c}_{vt}}', 'm', 'Vertical location of mean aerodynamic chord') Vvt = Variable('V_{vt}', '-', 'Vertical Tail Volume Coefficient') Vvtmin = Variable('V_{vt_{min}}', '-', 'Minimum Vertical Tail Volume Coefficient') #engine values Te = Variable('T_e', 'N', 'Thrust per engine at takeoff') #variables specific to yaw rate sizing Vland = Variable('V_{land}', 'm/s', 'Aircraft Landing Speed') CLvyaw = Variable('C_{L_{vt,yaw}}', '-', 'VT CL at rotation') Iz = Variable('I_{z, max}', 'kg*m^2', 'Aircraft Z-axis Moment of Inertia') rreq = Variable('\\dot{r}_{req}', 's^-2', 'Required Yaw Rate at Landing') #constraints constraints = [] with SignomialsEnabled(): #non vectorized constraints constraints.extend([ #constraint tail Cl at flare CLvyaw == .85 * CLvmax, LvtEO == 0.5 * rho0 * V1**2 * Svt * CLvtEO, # Vertical tail force (y-direction) for engine out TCS([CLvtEO * (1 + clvtEO / (np.pi * e * Avt)) <= clvtEO]), #engine out CL computation Avt == bvt**2 / Svt, # Tail geometry relationship Svt <= bvt * (croot + ctip) / 2, # [SP] # Fuselage length constrains the tail trailing edge TCS([p >= 1 + 2 * taper]), TCS([2 * q >= 1 + p]), # Mean aerodynamic chord calculations ymac == (bvt / 3) * q / p, zmac == (bvt / 3) * q / p, ## TCS([(2./3)*(1 + taper + taper**2)*croot/q >= cma]), # [SP] SignomialEquality( (2. / 3) * (1 + taper + taper**2) * croot / q, cma), # Define vertical tail geometry taper == ctip / croot, # Moment arm and geometry -- same as for htail dxlead + croot <= dxtrail, TCS([dxlead + ymac * tanL + 0.25 * cma >= lvt], reltol=1e-2), # [SP] # TODO: Constrain taper by tip Reynolds number taper >= 0.25, #Enforce a minimum vertical tail volume Vvt >= Vvtmin, ]) return constraints
def setup(self, Nclimb1, Nclimb2, Ncruise, substitutions = None, **kwargs): eng = 0 # vectorize with Vectorize(Nclimb1 +Nclimb2 + Ncruise): enginestate = FlightState() #build the submodel ac = Aircraft(Nclimb1 + Nclimb2, Ncruise, enginestate, eng) #Vectorize with Vectorize(Nclimb1): climb1 = ClimbSegment(ac) #Vectorize with Vectorize(Nclimb2): climb2 = ClimbSegment(ac) with Vectorize(Ncruise): cruise = CruiseClimbSegment(ac) statelinking = StateLinking(climb1.state, climb2.state, cruise.state, enginestate, Nclimb1, Nclimb2, Ncruise) #declare new variables W_ftotal = Variable('W_{f_{total}}', 'N', 'Total Fuel Weight') W_fclimb1 = Variable('W_{f_{climb1}}', 'N', 'Fuel Weight Burned in Climb 1') W_fclimb2 = Variable('W_{f_{climb2}}', 'N', 'Fuel Weight Burned in Climb 2') W_fcruise = Variable('W_{f_{cruise}}', 'N', 'Fuel Weight Burned in Cruise') W_total = Variable('W_{total}', 'N', 'Total Aircraft Weight') CruiseAlt = Variable('CruiseAlt', 'ft', 'Cruise Altitude [feet]') ReqRng = Variable('ReqRng', 'nautical_miles', 'Required Cruise Range') W_dry = Variable('W_{dry}', 'N', 'Aircraft Dry Weight') RCmin = Variable('RC_{min}', 'ft/min', 'Minimum allowed climb rate') dhftholdcl1 = Variable('dhftholdcl1', 'ft', 'Climb 1 Hold Variable') dhftholdcl2 = Variable('dhftholdcl2', 'ft', 'Climb 2 Hold Variable') dhftholdcr = Variable('dhftholdcr', 'ft', 'Cruise Hold Variable') h1 = climb1['h'] hftClimb1 = climb1['hft'] dhftcl1 = climb1['dhft'] h2 = climb2['h'] hftClimb2 = climb2['hft'] dhftcl2 = climb2['dhft'] dhftcr = cruise['dhft'] hftCruise = cruise['hft'] #make overall constraints constraints = [] with SignomialsEnabled(): constraints.extend([ #weight constraints TCS([ac['W_{e}'] + ac['W_{payload}'] + ac['numeng'] * ac['W_{engine}'] + ac['W_{wing}'] <= W_dry]), TCS([W_dry + W_ftotal <= W_total]), climb1['W_{start}'][0] == W_total, climb1['W_{end}'][-1] == climb2['W_{start}'][0], climb2['W_{end}'][-1] == cruise['W_{start}'][0], TCS([climb1['W_{start}'] >= climb1['W_{end}'] + climb1['W_{burn}']]), TCS([climb2['W_{start}'] >= climb2['W_{end}'] + climb2['W_{burn}']]), TCS([cruise['W_{start}'] >= cruise['W_{end}'] + cruise['W_{burn}']]), climb1['W_{start}'][1:] == climb1['W_{end}'][:-1], climb2['W_{start}'][1:] == climb2['W_{end}'][:-1], cruise['W_{start}'][1:] == cruise['W_{end}'][:-1], TCS([W_dry <= cruise['W_{end}'][-1]]), TCS([W_ftotal >= W_fclimb1 + W_fclimb2 + W_fcruise]), TCS([W_fclimb1 >= sum(climb1['W_{burn}'])]), TCS([W_fclimb2 >= sum(climb2['W_{burn}'])]), TCS([W_fcruise >= sum(cruise['W_{burn}'])]), #altitude constraints hftCruise[0] == CruiseAlt, ## TCS([hftCruise[1:Ncruise] >= hftCruise[:Ncruise-1] + dhftcr]), SignomialEquality(hftCruise[1:Ncruise], hftCruise[:Ncruise-1] + dhftholdcr), TCS([hftClimb2[1:Nclimb2] <= hftClimb2[:Nclimb2-1] + dhftholdcl2]), TCS([hftClimb2[0] <= dhftholdcl2 + 10000*units('ft')]), hftClimb2[-1] == hftCruise, TCS([hftClimb1[1:Nclimb1] >= hftClimb1[:Nclimb1-1] + dhftholdcl1]), TCS([hftClimb1[0] == dhftcl1[0]]), hftClimb1[-1] == 10000*units('ft'), #compute the dh2 dhftholdcl2 >= (hftCruise-10000*units('ft'))/Nclimb2, ## SignomialEquality(dhftholdcl2, (hftCruise-10000*units('ft'))/Nclimb2,), dhftholdcl2 == dhftcl2, #compute the dh1 dhftholdcl1 == 10000*units('ft')/Nclimb1, dhftholdcl1 == dhftcl1, dhftcr == dhftholdcr, sum(cruise['RngCruise']) + sum(climb2['RngClimb']) + sum(climb1['RngClimb']) >= ReqRng, #compute fuel burn from TSFC cruise['W_{burn}'] == ac['numeng']*ac.engine['TSFC'][Nclimb1 + Nclimb2:] * cruise['thr'] * ac.engine['F'][Nclimb1 + Nclimb2:], climb1['W_{burn}'] == ac['numeng']*ac.engine['TSFC'][:Nclimb1] * climb1['thr'] * ac.engine['F'][:Nclimb1], climb2['W_{burn}'] == ac['numeng']*ac.engine['TSFC'][Nclimb1:Nclimb1 + Nclimb2] * climb2['thr'] * ac.engine['F'][Nclimb1:Nclimb1 + Nclimb2], #min climb rate constraint ## climb1['RC'][0] >= RCmin, climb1['V'] <= 250*units('knots'), ]) M2 = .8 M25 = .6 M4a = .1025 Mexit = 1 M0 = .8 engineclimb1 = [ ac.engine.engineP['M_2'][:Nclimb1] == climb1['M'], ac.engine.engineP['M_{2.5}'] == M25, ac.engine.engineP['hold_{2}'] == 1+.5*(1.398-1)*M2**2, ac.engine.engineP['hold_{2.5}'] == 1+.5*(1.354-1)*M25**2, ac.engine.engineP['c1'] == 1+.5*(.401)*M0**2, #constraint on drag and thrust ac['numeng']*ac.engine['F_{spec}'][:Nclimb1] >= climb1['D'] + climb1['W_{avg}'] * climb1['\\theta'], #climb rate constraints TCS([climb1['excessP'] + climb1.state['V'] * climb1['D'] <= climb1.state['V'] * ac['numeng'] * ac.engine['F_{spec}'][:Nclimb1]]), ] M2 = .8 M25 = .6 M4a = .1025 Mexit = 1 M0 = .8 engineclimb2 = [ ac.engine.engineP['M_2'][Nclimb1:Nclimb1 + Nclimb2] == climb2['M'], #constraint on drag and thrust ac['numeng']*ac.engine['F_{spec}'][Nclimb1:Nclimb1 + Nclimb2] >= climb2['D'] + climb2['W_{avg}'] * climb2['\\theta'], #climb rate constraints TCS([climb2['excessP'] + climb2.state['V'] * climb2['D'] <= climb2.state['V'] * ac['numeng'] * ac.engine['F_{spec}'][Nclimb1:Nclimb1 + Nclimb2]]), ] M2 = .8 M25 = .6 M4a = .1025 Mexit = 1 M0 = .8 enginecruise = [ ac.engine.engineP['M_2'][Nclimb1 + Nclimb2:] == cruise['M'], ## cruise['M'] >= .7, #constraint on drag and thrust ac['numeng'] * ac.engine['F_{spec}'][Nclimb1 + Nclimb2:] >= cruise['D'] + cruise['W_{avg}'] * cruise['\\theta'], #climb rate constraints TCS([cruise['excessP'] + cruise.state['V'] * cruise['D'] <= cruise.state['V'] * ac['numeng'] * ac.engine['F_{spec}'][Nclimb1 + Nclimb2:]]), ] return constraints + ac + climb1 + climb2 + cruise + enginecruise + engineclimb1 + engineclimb2 + enginestate + statelinking
def setup(self, Nclimb, Ncruise, substitutions=None, **kwargs): eng = 0 # vectorize with Vectorize(Nclimb + Ncruise): enginestate = FlightState() #build the submodel ac = Aircraft(Nclimb, Ncruise, enginestate, eng) #Vectorize with Vectorize(Nclimb): climb = ClimbSegment(ac) with Vectorize(Ncruise): cruise = CruiseClimbSegment(ac) statelinking = StateLinking(climb.state, cruise.state, enginestate, Nclimb, Ncruise) #declare new variables W_ftotal = Variable('W_{f_{total}}', 'N', 'Total Fuel Weight') W_fclimb = Variable('W_{f_{climb}}', 'N', 'Fuel Weight Burned in Climb') W_fcruise = Variable('W_{f_{cruise}}', 'N', 'Fuel Weight Burned in Cruise') W_total = Variable('W_{total}', 'N', 'Total Aircraft Weight') CruiseAlt = Variable('CruiseAlt', 'ft', 'Cruise Altitude [feet]') ReqRng = Variable('ReqRng', 'nautical_miles', 'Required Cruise Range') W_dry = Variable('W_{dry}', 'N', 'Aircraft Dry Weight') dhftholdcl = Variable('dhftholdcl', 'ft', 'Climb Hold Variable') dhftholdcr = Variable('dhftholdcr', 'ft', 'Cruise Hold Variable') RCmin = Variable('RC_{min}', 'ft/min', 'Minimum allowed climb rate') h = climb['h'] hftClimb = climb['hft'] dhftcl = climb['dhft'] dhftcr = cruise['dhft'] hftCruise = cruise['hft'] #make overall constraints constraints = [] with SignomialsEnabled(): constraints.extend([ #weight constraints TCS([ ac['W_{e}'] + ac['W_{payload}'] + ac['numeng'] * ac['W_{engine}'] + ac['W_{wing}'] <= W_dry ]), TCS([W_dry + W_ftotal <= W_total]), climb['W_{start}'][0] == W_total, climb['W_{end}'][-1] == cruise['W_{start}'][0], # similar constraint 1 TCS([ climb['W_{start}'] >= climb['W_{end}'] + climb['W_{burn}'] ]), # similar constraint 2 TCS([ cruise['W_{start}'] >= cruise['W_{end}'] + cruise['W_{burn}'] ]), climb['W_{start}'][1:] == climb['W_{end}'][:-1], cruise['W_{start}'][1:] == cruise['W_{end}'][:-1], TCS([W_dry <= cruise['W_{end}'][-1]]), TCS([W_ftotal >= W_fclimb + W_fcruise]), TCS([W_fclimb >= sum(climb['W_{burn}'])]), TCS([W_fcruise >= sum(cruise['W_{burn}'])]), #altitude constraints hftCruise[0] == CruiseAlt, ## TCS([hftCruise[1:Ncruise] >= hftCruise[:Ncruise-1] + dhftcr]), SignomialEquality(hftCruise[1:Ncruise], hftCruise[:Ncruise - 1] + dhftholdcr), TCS([hftClimb[1:Nclimb] >= hftClimb[:Nclimb - 1] + dhftholdcl ]), TCS([hftClimb[0] >= dhftcl[0]]), hftClimb[-1] <= hftCruise, #compute the dh dhftholdcl == hftCruise[0] / Nclimb, dhftcl == dhftholdcl, dhftcr == dhftholdcr, sum(cruise['RngCruise']) + sum(climb['RngClimb']) >= ReqRng, #compute fuel burn from TSFC cruise['W_{burn}'] == ac['numeng'] * ac.engine['TSFC'][Nclimb:] * cruise['thr'] * ac.engine['F'][Nclimb:], climb['W_{burn}'] == ac['numeng'] * ac.engine['TSFC'][:Nclimb] * climb['thr'] * ac.engine['F'][:Nclimb], #min climb rate constraint ## climb['RC'][0] >= RCmin, ]) M2 = .8 M25 = .6 M4a = .1025 Mexit = 1 M0 = .8 engineclimb = [ ac.engine.engineP['M_2'][:Nclimb] == climb['M'], ac.engine.engineP['M_{2.5}'] == M25, ac.engine.engineP['hold_{2}'] == 1 + .5 * (1.398 - 1) * M2**2, ac.engine.engineP['hold_{2.5}'] == 1 + .5 * (1.354 - 1) * M25**2, ac.engine.engineP['c1'] == 1 + .5 * (.401) * M0**2, #constraint on drag and thrust ac['numeng'] * ac.engine['F'][:Nclimb] >= climb['D'] + climb['W_{avg}'] * climb['\\theta'], #climb rate constraints TCS([ climb['excessP'] + climb.state['V'] * climb['D'] <= climb.state['V'] * ac['numeng'] * ac.engine['F'][:Nclimb] ]), ] M2 = .8 M25 = .6 M4a = .1025 Mexit = 1 M0 = .8 enginecruise = [ ac.engine.engineP['M_2'][Nclimb:] == cruise['M'], ## cruise['M'] == .8, cruise['M'] >= .76, ac.engine.engineP['M_{2.5}'][2] == M25, ac.engine.engineP['M_{2.5}'][3] == M25, #constraint on drag and thrust ac['numeng'] * ac.engine['F'][Nclimb:] >= cruise['D'] + cruise['W_{avg}'] * cruise['\\theta'], #climb rate constraints TCS([ cruise['excessP'] + cruise.state['V'] * cruise['D'] <= cruise.state['V'] * ac['numeng'] * ac.engine['F'][Nclimb:] ]), ] return constraints + ac + climb + cruise + enginecruise + engineclimb + enginestate + statelinking