Exemplo n.º 1
0
    def setup(self, **kwargs):
        self.wns = WingNoStruct()
        self.wb = WingBox(self.wns, "wing")

        Wwing = Variable('W_{wing}', 'N', 'Wing System Weight')

        Cwing = Variable('C_{wing}', 1, '-', 'Wing Weight Margin and Sensitivity Factor')

        # w.r.t. the quarter chord of the root of the wing.
        dxACwing = Variable('\\Delta x_{AC_{wing}}','m','Wing Aerodynamic Center Shift')

        #wing induced drag reduction due to wing tip devices
        TipReduct = Variable('TipReduct', '-', 'Induced Drag Reduction Factor from Wing Tip Devices')

        constraints = []
        with SignomialsEnabled():
            constraints.extend([
            self.wns['\\lambda'] == self.wb['taper'],

            TCS([Wwing >= Cwing * self.wb['W_{struct}'] + self.wb['W_{struct}']*(self.wns['f_{flap}'] + \
                    self.wns['f_{slat}'] + self.wns['f_{aileron}'] + self.wns['f_{lete}'] + self.wns['f_{ribs}'] + \
                    self.wns['f_{spoiler}'] + self.wns['f_{watt}'])]),
            TCS([dxACwing <= 1./24.*(self.wns['c_{root}'] + 5.*self.wns['c_{tip}'])/self.wns['S'] \
                            *self.wns['b']**2*self.wns['\\tan(\\Lambda)']]),
            ])

        return self.wns, self.wb, constraints
Exemplo n.º 2
0
    def setup(self, aircraft, state, **kwargs):
        self.aircraft = aircraft
        self.aircraftP = aircraft.dynamic(state)
        self.wingP = self.aircraftP.wingP
        self.fuseP = self.aircraftP.fuseP
        self.engineP = self.aircraftP.engineP
                        
        #variable definitions
        z_bre = Variable('z_{bre}', '-', 'Breguet Parameter')
        Rng = Variable('Rng', 'nautical_miles', 'Cruise Segment Range')

        constraints = []

        constraints.extend([
             #steady level flight constraint on D 
             self.aircraftP['D'] == aircraft['numeng'] * self.engineP['F'],

             #taylor series expansion to get the weight term
             TCS([self.aircraftP['W_{burn}']/self.aircraftP['W_{end}'] >=
                  te_exp_minus1(z_bre, nterm=3)]),

             #breguet range eqn
             TCS([z_bre >= (self.engineP['TSFC'] * self.aircraftP['thr']*
                            self.aircraftP['D']) / self.aircraftP['W_{avg}']]),

             #time
             self.aircraftP['thr'] * state['V'] == Rng,
             ])

        return constraints, self.aircraftP
Exemplo n.º 3
0
    def setup(self, static, state, N=5):
        exec parse_variables(BladeElementProp.__doc__)

        with Vectorize(N):
            blade = BladeElementPerf(static, state)

        constraints = [
            blade.dr == static.R / (N), blade.omega == omega,
            blade.r[0] == static.R / (2. * N)
        ]

        for n in range(1, N):
            constraints += [
                TCS([blade.r[n] >= blade.r[n - 1] + static.R / N]),
                blade.eta_i[n] == blade.eta_i[n - 1],
            ]

        constraints += [
            TCS([Q >= sum(blade.dQ)]), eta == state.V * T / (omega * Q),
            blade.M[-1] <= Mtip, static.T_m >= T, omega <= omega_max
        ]

        with SignomialsEnabled():
            constraints += [TCS([T <= sum(blade.dT)])]

        return constraints, blade
Exemplo n.º 4
0
    def setup(self, wing, state, **kwargs):
        #new variables
        CL= Variable('C_{L}', '-', 'Lift Coefficient')
        Cdw = Variable('C_{d_w}', '-', 'Cd for a NC130 Airfoil at Re=2e7')
        Dwing = Variable('D_{wing}', 'N', 'Total Wing Drag')
        Lwing = Variable('L_{wing}', 'N', 'Wing Lift')

        CLaw    = Variable('C_{L_{\\alpha,w}}', '-', 'Lift curve slope, wing')

        #constraints
        constraints = []

        constraints.extend([
            #airfoil drag constraint
            Lwing == (.5*wing['S']*state.atm['\\rho']*state['V']**2)*CL,
            TCS([Cdw**6.5 >= (1.02458748e10 * CL**15.587947404823325 * state['M']**156.86410659495155 +
                         2.85612227e-13 * CL**1.2774976672501526 * state['M']**6.2534328002723703 +
                         2.08095341e-14 * CL**0.8825277088649582 * state['M']**0.0273667615730107 +
                         1.94411925e+06 * CL**5.6547413360261691 * state['M']**146.51920742858428)]),
            TCS([Dwing >= (.5*wing['S']*state.atm['\\rho']*state['V']**2)*(Cdw + wing['K']*CL**2)]),

            CLaw == 5,
            ])

        return constraints
Exemplo n.º 5
0
    def setup(self, aircraft, state, **kwargs):
        self.aircraft = aircraft
        self.aircraftP = AircraftP(aircraft, state)
        self.wingP = self.aircraftP.wingP
        self.fuseP = self.aircraftP.fuseP
        self.engineP = self.aircraftP.engineP
                        
        #variable definitions
        z_bre = Variable('z_{bre}', '-', 'Breguet Parameter')
        Rng = Variable('Rng', 'nautical_miles', 'Cruise Segment Range')
        TotRng = Variable('TotRng', 'nautical_miles', 'Total Cruise Range')

        #new varibales for the TASOPT flight profile
        gammaCruise = Variable('\\gamma_{cruise}', '-', 'Cruise Climb Angle')
        RCCruise = Variable('RC_{cruise}', 'ft/min', 'Cruise Climb Rate')
        excessP = Variable('P_{excess}', 'W', 'Excess Power During Cruise')

        constraints = []

##        constraints.extend([
             #taylor series expansion to get the weight term
##             TCS([self.aircraftP['W_{burn}']/self.aircraftP['W_{end}'] >=
##                  te_exp_minus1(z_bre, nterm=3)]),
##
##             #breguet range eqn
##             TCS([z_bre >= (self.engineP['TSFC'] * self.aircraftP['thr']*
##                            self.aircraftP['D']) / self.aircraftP['W_{avg}']]),

##             #time
##             self.aircraftP['thr'] * state['V'] == Rng,
##             ])

        #new constarints for the TASOPT flight profile

        with SignomialsEnabled():
            constraints.extend([
                #compute the cruise climb angle
                state['\\rho']*self.aircraftP['V']**2 == gammaCruise * state["P_{atm}"] * self.aircraftP['M']**2,
                
                #compute the cruise climb rate
                self.aircraftP['V'] * gammaCruise == RCCruise,

                #constraint on drag and thrust
                self.aircraft['numeng']*self.engineP['thrust'] >= self.aircraftP['D'] + self.aircraftP['W_{avg}'] * gammaCruise,

                RCCruise == excessP/self.aircraftP['W_{avg}'],

                #climb rate constraints
                TCS([excessP + state['V'] * self.aircraftP['D'] <=  state['V'] * aircraft['numeng'] * self.engineP['thrust']]),

                #time
                TCS([self.aircraftP['thr'] * state['V'] >= Rng + (.5*gammaCruise**2)*self.aircraftP['thr'] * state['V']]),
                ])

        return constraints, self.aircraftP
Exemplo n.º 6
0
    def setup(self, aircraft):

        fs = FlightState()

        A = Variable("A", "m/s**2", "log fit equation helper 1")
        B = Variable("B", "1/m", "log fit equation helper 2")

        g = Variable("g", 9.81, "m/s**2", "gravitational constant")
        mu = Variable("\\mu", 0.5, "-", "Braking coefficient of friction")
        T_rev = Variable("T", "N", "Reverse thrust")
        cda = Variable("CDA", 0.024, "-", "parasite drag coefficient")

        CLg = Variable("C_{L_g}", "-", "ground lift coefficient")
        CDg = Variable("C_{D_g}", "-", "grag ground coefficient")
        Vstall = Variable("V_{stall}", "knots", "stall velocity")
        Sgr = Variable("S_{gr}", "ft", "landing ground roll")
        Slnd = Variable("S_{land}", "ft", "landing distance")
        etaprop = Variable("\\eta_{prop}", 0.05, "-", "propellor efficiency")
        msafety = Variable("m_{fac}", 1.4, "-", "Landing safety margin")
        CLland = Variable("C_{L_{land}}", 3.5, "-", "landing CL")
        cdp = Variable("c_{d_{p_{stall}}}", 0.025, "-",
                       "profile drag at Vstallx1.2")
        V_ref = Variable("V_{ref}", "kts", "Approach reference speed")
        f_ref = Variable("f_{ref}", 1.3, "-",
                         "Approach reference speed margin above stall")
        path = os.path.dirname(os.path.abspath(__file__))
        df = pd.read_csv(path + os.sep + "logfit.csv")
        fd = df.to_dict(orient="records")[0]

        constraints = [
            T_rev == aircraft["P_{shaft-max}"] * etaprop / fs["V"],
            Vstall == (2. * aircraft.topvar("W") / fs["\\rho"] /
                       aircraft["S"] / CLland)**0.5,
            fs["V"] >= f_ref * Vstall,
            V_ref == fs["V"],
            Slnd >= msafety * Sgr,
            FitCS(fd, Sgr * 2 * B, [A / g, B * fs["V"]**2 / g]),
        ]

        with SignomialsEnabled():
            constraints.extend([
                TCS([(B * aircraft.topvar("W") / g +
                      0.5 * fs["\\rho"] * aircraft["S"] * CDg >=
                      0.5 * fs["\\rho"] * aircraft["S"] * mu * CLland)]),
                TCS([A / g <= T_rev / aircraft.topvar("W") + mu]),
                CDg <=
                cda + cdp + CLland**2 / pi / aircraft["AR"] / aircraft["e"],
            ])

        return constraints, fs
Exemplo n.º 7
0
    def setup(self, aircraft, state, **kwargs):
        self.aircraft = aircraft
        self.aircraftP = AircraftP(aircraft, state)
        self.wingP = self.aircraftP.wingP
        self.fuseP = self.aircraftP.fuseP

        #variable definitions
        z_bre = Variable('z_{bre}', '-', 'Breguet Parameter')
        Rng = Variable('Rng', 'nautical_miles', 'Cruise Segment Range')

        constraints = []

        constraints.extend([
            #taylor series expansion to get the weight term
            TCS([
                self.aircraftP['W_{burn}'] / self.aircraftP['W_{end}'] >=
                te_exp_minus1(z_bre, nterm=3)
            ]),

            #time
            self.aircraftP['thr'] * state['V'] == Rng,
            self.aircraftP['W_{burn}'] == self.aircraft.engine['TSFC'][2:] *
            self.aircraft.engine['F'][:2:] * self.aircraftP['thr']
        ])

        return constraints, self.aircraftP
    def setup(self, aircraft, state, **kwargs):
        #make submodels
        self.aircraft = aircraft
        self.wingP = aircraft.wing.dynamic(state)
        self.fuseP = aircraft.fuse.dynamic(state)
        self.engineP = aircraft.engine.dynamic(state)

        self.Pmodels = [self.wingP, self.fuseP, self.engineP]

        #variable definitions
        Vstall = Variable('V_{stall}', 'knots', 'Aircraft Stall Speed')
        D = Variable('D', 'N', 'Total Aircraft Drag')
        W_avg = Variable('W_{avg}', 'N',
                         'Geometric Average of Segment Start and End Weight')
        W_start = Variable('W_{start}', 'N', 'Segment Start Weight')
        W_end = Variable('W_{end}', 'N', 'Segment End Weight')
        W_burn = Variable('W_{burn}', 'N', 'Segment Fuel Burn Weight')
        WLoadmax = Variable('W_{Load_{max}}', 'N/m^2', 'Max Wing Loading')
        WLoad = Variable('W_{Load}', 'N/m^2', 'Wing Loading')
        t = Variable('tmin', 'min', 'Segment Flight Time in Minutes')
        thours = Variable('thr', 'hour', 'Segment Flight Time in Hours')

        constraints = []

        constraints.extend([
            #speed must be greater than stall speed
            state['V'] >= Vstall,

            #Figure out how to delete
            Vstall == 120 * units('kts'),
            WLoadmax == 6664 * units('N/m^2'),

            #compute the drag
            TCS([D >= self.wingP['D_{wing}'] + self.fuseP['D_{fuse}']]),

            #constraint CL and compute the wing loading
            W_avg == .5 * self.wingP['C_{L}'] * self.aircraft['S'] *
            state.atm['\\rho'] * state['V']**2,
            WLoad == .5 * self.wingP['C_{L}'] * self.aircraft['S'] *
            state.atm['\\rho'] * state['V']**2 / self.aircraft.wing['S'],

            #set average weight equal to the geometric avg of start and end weight
            W_avg == (W_start * W_end)**.5,

            #constrain the max wing loading
            WLoad <= WLoadmax,

            #compute fuel burn from TSFC
            W_burn == aircraft['numeng'] * self.engineP['TSFC'] * thours *
            self.engineP['thrust'],

            #time unit conversion
            t == thours,

            #make lift equal weight --> small angle approx in climb
            self.wingP['L_{wing}'] == W_avg,
        ])

        return constraints, self.wingP, self.engineP, self.fuseP
Exemplo n.º 9
0
    def setup(self, aircraft, state, **kwargs):
        #submodels
        self.aircraft = aircraft
        self.aircraftP = AircraftP(aircraft, state)
        self.wingP = self.aircraftP.wingP
        self.fuseP = self.aircraftP.fuseP
        self.engineP = self.aircraftP.engineP
                                  
        #variable definitions
        theta = Variable('\\theta', '-', 'Aircraft Climb Angle')
        excessP = Variable('P_{excess}', 'W', 'Excess Power During Climb')
        RC = Variable('RC', 'feet/min', 'Rate of Climb/Decent')
        dhft = Variable('dhft', 'feet', 'Change in Altitude Per Climb Segment [feet]')
        RngClimb = Variable('R_{climb}', 'nautical_miles', 'Down Range Distance Covered in Each Climb Segment')
        TotRngClimb = Variable('TotRngClimb', 'nautical_miles', 'Down Range Distance Covered in Climb')

        #constraints
        constraints = []
        
        constraints.extend([
           #constraint on drag and thrust
            self.aircraft['numeng']*self.engineP['thrust'] >= self.aircraftP['D'] + self.aircraftP['W_{avg}'] * theta,
            
            #climb rate constraints
            TCS([excessP + state['V'] * self.aircraftP['D'] <=  state['V'] * aircraft['numeng'] * self.engineP['thrust']]),
            
            RC == excessP/self.aircraftP['W_{avg}'],
            RC >= 500*units('ft/min'),
            
            #make the small angle approximation and compute theta
            theta * state['V']  == RC,
           
            dhft == self.aircraftP['tmin'] * RC,
        
            #makes a small angle assumption during climb
##            RngClimb == self.aircraftP['thr']*state['V'],
            ])

        with SignomialsEnabled():
            constraints.extend([
                #time
                TCS([self.aircraftP['thr'] * state['V'] >= RngClimb + (.5*theta**2)*self.aircraftP['thr'] * state['V']]),
                ])

        return constraints, self.aircraftP
Exemplo n.º 10
0
    def setup(self, aircraft, state, **kwargs):
        self.aircraft = aircraft
        self.aircraftP = AircraftP(aircraft, state)
        self.wingP = self.aircraftP.wingP
        self.fuseP = self.aircraftP.fuseP
        self.engineP = self.aircraftP.engineP

        #variable definitions
        z_bre = Variable('z_{bre}', '-', 'Breguet Parameter')
        Rng = Variable('Rng', 'nautical_miles', 'Cruise Segment Range')

        constraints = []

        constraints.extend([
            #steady level flight constraint on D
            self.aircraftP['D'] == aircraft['numeng'] * self.engineP['thrust'],

            #taylor series expansion to get the weight term
            TCS([
                self.aircraftP['W_{burn}'] / self.aircraftP['W_{end}'] >=
                te_exp_minus1(z_bre, nterm=3)
            ]),

            #breguet range eqn
            # old version -- possibly unneeded numeng
            #            TCS([z_bre >= (self.aircraft['numeng'] * self.engineP['TSFC'] * self.aircraftP['thr']*
            #                           self.aircraftP['D']) / self.aircraftP['W_{avg}']]),

            # new version -- needs to be thought through carefully
            # seems correct to me - I switched T to D below (steady level flight) but fogot
            #about the Negn term
            TCS([
                z_bre >= (self.engineP['TSFC'] * self.aircraftP['thr'] *
                          self.aircraftP['D']) / self.aircraftP['W_{avg}']
            ]),

            #time
            self.aircraftP['thr'] * state['V'] == Rng,
        ])

        return constraints, self.aircraftP
Exemplo n.º 11
0
    def setup(self):

        Wing.fillModel = None
        self.wing = Wing()

        W = Variable("W", "lbf", "aircraft weight")
        WS = Variable("W/S", "lbf/ft^2", "Aircraft wing loading")
        PW = Variable("P/W", "hp/lbf", "Aircraft shaft hp/weight ratio")
        Wpay = Variable("W_{pay}", 2 * 195, "lbf", "payload weight")
        hbatt = Variable("h_{batt}", 210, "W*hr/kg", "battery specific energy")
        etae = Variable("\\eta_{e}", 0.9, "-", "total electrical efficiency")
        Wbatt = Variable("W_{batt}", "lbf", "battery weight")
        Wwing = Variable("W_{wing}", "lbf", "wing weight")
        Pshaftmax = Variable("P_{shaft-max}", "W", "max shaft power")
        sp_motor = Variable("sp_{motor}", 7. / 9.81, "kW/N",
                            'Motor specific power')
        Wmotor = Variable("W_{motor}", "lbf", "motor weight")
        Wcent = Variable("W_{cent}", "lbf", "aircraft center weight")
        fstruct = Variable("f_{struct}", 0.2, "-",
                           "structural weight fraction")
        Wstruct = Variable("W_{struct}", "lbf", "structural weight")
        e = Variable("e", 0.8, "-", "span efficiency factor")
        CL_max_clean = Variable("CL_{max_{clean}}", 1.6, "-", "Clean CL max")
        CL_max_to = Variable("CL_{max_{to}}", 2.0, "-", "Clean CL max")
        CL_max_aprch = Variable("CL_{max_{aprch}}", 2.4, "-", "Clean CL max")
        fbattmax = Variable("f_{batt,max}", 1.0, "-", "max battery fraction")

        loading = self.wing.spar.loading(self.wing)
        loading.substitutions.update({
            loading.kappa: 0.05,
            self.wing.spar.material.sigma: 1.5e9,
            loading.Nmax: 6,
            self.wing.skin.material.tmin: 0.012 * 4,
            self.wing.mfac: 1.4,
            self.wing.spar.mfac: 0.8
        })
        constraints = [
            Wcent == loading.W,
            WS == W / self.wing.planform.S,
            PW == Pshaftmax / W,
            TCS([W >= Wbatt + Wpay + self.wing.W + Wmotor + Wstruct]),
            Wcent >= Wbatt + Wpay + Wmotor + Wstruct,
            Wstruct >= fstruct * W,
            Wmotor >= Pshaftmax / sp_motor,
            Wbatt / W <= fbattmax,
        ]

        return constraints, self.wing, loading
Exemplo n.º 12
0
    def setup(self, Wstart, Wend, perf):
        z_bre = Variable("z_{bre}", "-", "Breguet coefficient")
        Wfuel = Variable("W_{fuel}", "lbf", "segment-fuel weight")
        g = Variable("g", 9.81, "m/s^2", "gravitational acceleration")
        R = Variable("R", "nautical_miles", "range")
        rhofuel = Variable("\\rho_{JetA}", 6.75, "lb/gallon",
                           "Jet A fuel density")

        constraints = [
            TCS([
                z_bre >= (R * perf["\\dot{m}"] * rhofuel * g / perf["V"] /
                          (Wend * Wstart)**0.5)
            ]), Wfuel / Wend >= te_exp_minus1(z_bre, 3), Wstart >= Wend + Wfuel
        ]

        return constraints
Exemplo n.º 13
0
    def setup(self, perf):
        z_bre = Variable("z_{bre}", "-", "Breguet coefficient")
        t = Variable("t", "days", "Time per flight segment")
        f_fueloil = Variable("f_{(fuel/oil)}", 0.98, "-", "Fuel-oil fraction")
        Wfuel = Variable("W_{fuel}", "lbf", "Segment-fuel weight")
        g = Variable("g", 9.81, "m/s^2", "gravitational acceleration")

        constraints = [
            TCS([
                z_bre >= (perf["P_{total}"] * t * perf["BSFC"] * g /
                          (perf["W_{end}"] * perf["W_{start}"])**0.5)
            ]), f_fueloil * Wfuel / perf["W_{end}"] >= te_exp_minus1(z_bre, 3),
            perf["W_{start}"] >= perf["W_{end}"] + Wfuel
        ]

        return constraints
Exemplo n.º 14
0
    def setup(self, static, state):
        exec parse_variables(BladeElementPerf.__doc__)

        V = state.V
        rho = state.rho
        R = static.R
        mu = state.mu
        path = os.path.dirname(__file__)
        fd = pd.read_csv(path + os.sep +
                         "dae51_fitdata.csv").to_dict(orient="records")[0]
        c = static.c
        constraints = [
            TCS([Wa >= V + va]),
            TCS([Wt + vt <= omega * r]),
            TCS([G == (1. / 2.) * Wr * c * cl]),
            F == (2. / pi) * (1.01116 * f**.0379556)
            **(10),  #This is the GP fit of arccos(exp(-f))
            M == Wr / a,
            lam_w == (r / R) * (Wa / Wt),
            va == vt * (Wt / Wa),
            eps == cd / cl,
            TCS([dQ >= rho * B * G * (Wa + eps * Wt) * r * dr]),
            AR_b == R / c,
            AR_b <= AR_b_max,
            Re == Wr * c * rho / mu,
            eta_i == (V / (omega * r)) * (Wt / Wa),
            TCS([f + (r / R) * B / (2 * lam_w) <= (B / 2.) * (1. / lam_w)]),
            XfoilFit(fd, cd, [cl, Re], name="polar"),
            cl <= cl_max
        ]
        with SignomialsEnabled():
            constraints += [
                SignomialEquality(Wr**2, (Wa**2 + Wt**2)),
                TCS([dT <= rho * B * G * (Wt - eps * Wa) * dr]),
                TCS([
                    vt**2 * F**2 * (1. + (4. * lam_w * R / (pi * B * r))**2) >=
                    (B * G / (4. * pi * r))**2
                ]),
            ]
        return constraints, state
Exemplo n.º 15
0
    def setup(self, Nmissions, **kwargs):
        g = Variable('g', 9.81, 'm*s^-2', 'Acceleration due to gravity')
        dPover = Variable('\\Delta P_{over}', 'psi', 'Cabin overpressure')
        with Vectorize(Nmissions):
            npass = Variable('n_{pass}', '-', 'Number of passengers')
        Nland = Variable('N_{land}', 6.0, '-',
                         'Emergency landing load factor')  # [TAS]
        Nlift = Variable('N_{lift}', '-', 'Wing maximum load factor')
        SPR = Variable('SPR', '-', 'Number of seats per row')
        nrows = Variable('n_{rows}', '-', 'Number of rows')
        nseat = Variable('n_{seat}', '-', 'Number of seats')
        pitch = Variable('p_s', 'cm', 'Seat pitch')

        # Cross-sectional variables
        Adb = Variable('A_{db}', 'm^2', 'Web cross sectional area')
        Afloor = Variable('A_{floor}', 'm^2', 'Floor beam x-sectional area')
        Afuse = Variable('A_{fuse}', 'm^2', 'Fuselage x-sectional area')
        Askin = Variable('A_{skin}', 'm^2', 'Skin cross sectional area')
        hdb = Variable('h_{db}', 'm', 'Web half-height')
        hfloor = Variable('h_{floor}', 'm', 'Floor beam height')
        hfuse = Variable('h_{fuse}', 'm', 'Fuselage height')
        dRfuse = Variable('\\Delta R_{fuse}', 'm', 'Fuselage extension height')
        Rfuse = Variable('R_{fuse}', 'm', 'Fuselage radius')
        tdb = Variable('t_{db}', 'm', 'Web thickness')
        thetadb = Variable('\\theta_{db}', '-', 'DB fuselage joining angle')
        tshell = Variable('t_{shell}', 'm', 'Shell thickness')
        tskin = Variable('t_{skin}', 'm', 'Skin thickness')
        waisle = Variable('w_{aisle}', 'm', 'Aisle width')
        wdb = Variable('w_{db}', 'm', 'DB added half-width')
        wfloor = Variable('w_{floor}', 'm', 'Floor half-width')
        wfuse = Variable('w_{fuse}', 'm', 'Fuselage half-width')
        wseat = Variable('w_{seat}', 'm', 'Seat width')
        wsys = Variable('w_{sys}', 'm',
                        'Width between cabin and skin for systems')

        # Tail cone variables
        lamcone = Variable('\\lambda_{cone}', '-',
                           'Tailcone radius taper ratio')
        lcone = Variable('l_{cone}', 'm', 'Cone length')
        plamv = Variable('p_{\\lambda_{vt}}', 1.6, '-',
                         '1 + 2*Tail taper ratio')
        # tcone = Variable('t_{cone}', 'm', 'Cone thickness') # perhaps to be added later

        # Lengths
        c0 = Variable('c_0', 'm', 'Root chord of the wing')
        lfuse = Variable('l_{fuse}', 'm', 'Fuselage length')
        lnose = Variable('l_{nose}', 'm', 'Nose length')
        lshell = Variable('l_{shell}', 'm', 'Shell length')
        lfloor = Variable('l_{floor}', 'm', 'Floor length')

        # Surface areas
        Sbulk = Variable('S_{bulk}', 'm^2', 'Bulkhead surface area')
        Snose = Variable('S_{nose}', 'm^2', 'Nose surface area')

        # Volumes
        Vbulk = Variable('V_{bulk}', 'm^3', 'Bulkhead skin volume')
        Vcabin = Variable('V_{cabin}', 'm^3', 'Cabin volume')
        Vcone = Variable('V_{cone}', 'm^3', 'Cone skin volume')
        Vcyl = Variable('V_{cyl}', 'm^3', 'Cylinder skin volume')
        Vdb = Variable('V_{db}', 'm^3', 'Web volume')
        Vfloor = Variable('V_{floor}', 'm^3', 'Floor volume')
        Vnose = Variable('V_{nose}', 'm^3', 'Nose skin volume')

        # Loads
        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')

        # Floor loads
        Mfloor = Variable('M_{floor}', 'N*m',
                          'Max bending moment in floor beams')
        Pfloor = Variable('P_{floor}', 'N', 'Distributed floor load')
        Sfloor = Variable('S_{floor}', 'N', 'Maximum shear in floor beams')
        sigfloor = Variable('\\sigma_{floor}', 'N/m^2',
                            'Max allowable floor stress')
        taucone = Variable('\\tau_{cone}', 'N/m^2', 'Shear stress in cone')
        taufloor = Variable('\\tau_{floor}', 'N/m^2',
                            'Max allowable shear web stress')

        # Bending inertias (ported from TASOPT)
        # (shell inertia contribution)
        A0h = Variable('A_{0h}', 'm^2', 'Horizontal bending area constant A0h')

        # (tail impact + aero loading)
        A1hLand = Variable(
            'A_{1h_{Land}}', 'm',
            'Horizontal bending area constant A1h (landing case)')
        A1hMLF = Variable(
            'A_{1h_{MLF}}', 'm',
            'Horizontal bending area constant A1h (max aero load case)')

        # (fuselage impact)
        A2hLand = Variable(
            'A_{2h_{Land}}', '-',
            'Horizontal bending area constant A2h (landing case)')
        A2hMLF = Variable(
            'A_{2h_{MLF}}', '-',
            'Horizontal bending area constant A2h (max aero load case)')

        AhbendbLand = Variable(
            'A_{hbendb_{Land}}', 'm^2',
            'Horizontal bending area at rear wingbox (landing case)')
        AhbendbMLF = Variable(
            'A_{hbendb_{MLF}}', 'm^2',
            'Horizontal bending area at rear wingbox (max aero load case)')

        AhbendfLand = Variable(
            'A_{hbendf_{Land}}', 'm^2',
            'Horizontal bending area at front wingbox (landing case)')
        AhbendfMLF = Variable(
            'A_{hbendf_{MLF}}', 'm^2',
            'Horizontal bending area at front wingbox (max aero load case)')

        Avbendb = Variable('A_{vbend_{b}}', 'm^2',
                           'Vertical bending material area at rear wingbox')

        B0v = Variable(
            'B_{0v}', 'm^2',
            'Vertical bending area constant B0')  #(shell inertia contribution)
        B1v = Variable('B_{1v}', 'm', 'Vertical bending area constant B1')
        # #(vertical tail bending load)
        Ihshell = Variable('I_{h_{shell}}', 'm^4',
                           'Shell horizontal bending inertia')
        Ivshell = Variable('I_{v_{shell}}', 'm^4',
                           'Shell vertical bending inertia')
        rMh = Variable('r_{M_h}', .4, '-',
                       'Horizontal inertial relief factor')  # [TAS]
        rMv = Variable('r_{M_v}', .7, '-',
                       'Vertical inertial relief factor')  # [TAS]
        sigbend = Variable('\\sigma_{bend}', 'N/m^2',
                           'Bending material stress')
        sigMh = Variable('\\sigma_{M_h}', 'N/m^2',
                         'Horizontal bending material stress')
        sigMv = Variable('\\sigma_{M_v}', 'N/m^2',
                         'Vertical bending material stress')
        Vhbend = Variable('V_{hbend}', 'm^3',
                          'Horizontal bending material volume')

        Vhbendb = Variable(
            'V_{hbend_{b}}', 'm^3',
            'Horizontal bending material volume b')  # back fuselage
        Vhbendc = Variable(
            'V_{hbend_{c}}', 'm^3',
            'Horizontal bending material volume c')  # center fuselage
        Vhbendf = Variable(
            'V_{hbend_{f}}', 'm^3',
            'Horizontal bending material volume f')  # front fuselage

        Vvbend = Variable('V_{vbend}', 'm^3',
                          'Vertical bending material volume')
        Vvbendb = Variable(
            'V_{vbend_{b}}', 'm^3',
            'Vertical bending material volume b')  #back fuselage
        Vvbendc = Variable(
            'V_{vbend_{c}}', 'm^3',
            'Vertical bending material volume c')  #center fuselage

        Whbend = Variable('W_{hbend}', 'lbf',
                          'Horizontal bending material weight')
        Wvbend = Variable('W_{vbend}', 'lbf',
                          'Vertical bending material weight')

        xhbendLand = Variable(
            'x_{hbend_{Land}}', 'ft',
            'Horizontal zero bending location (landing case)')
        xhbendMLF = Variable(
            'x_{hbend_{MLF}}', 'ft',
            'Horizontal zero bending location (maximum aero load case)')
        xvbend = Variable('x_{vbend}', 'ft', 'Vertical zero bending location')

        # Material properties
        rE = Variable(
            'r_E', 1., '-',
            'Ratio of stringer/skin moduli')  # [TAS] # [b757 freight doc]
        rhocargo = Variable('\\rho_{cargo}', 150, 'kg/m^3', 'Cargo density')
        rhocone = Variable('\\rho_{cone}', 'kg/m^3',
                           'Cone material density')  # [TAS]
        rhobend = Variable('\\rho_{bend}', 'kg/m^3',
                           'Stringer density')  # [TAS]
        rhofloor = Variable('\\rho_{floor}', 'kg/m^3',
                            'Floor material density')  # [TAS]
        rholugg = Variable('\\rho_{lugg}', 100, 'kg/m^3',
                           'Luggage density')  # [Philippe]
        rhoskin = Variable('\\rho_{skin}', 'kg/m^3', 'Skin density')  # [TAS]
        Wppfloor = Variable('W\'\'_{floor}', 'N/m^2',
                            'Floor weight/area density')  # [TAS]
        Wppinsul = Variable(
            'W\'\'_{insul}', 'N/m^2',
            'Weight/area density of insulation material')  # [TAS]
        Wpseat = Variable('W\'_{seat}', 'N', 'Weight per seat')  # [TAS]
        Wpwindow = Variable('W\'_{window}', 'N/m',
                            'Weight/length density of windows')  # [TAS]

        # Weight fractions
        fapu = Variable('f_{apu}', 0.035, '-',
                        'APU weight as fraction of payload weight')  # [TAS]
        ffadd = Variable(
            'f_{fadd}', '-',
            'Fractional added weight of local reinforcements')  # [TAS]
        fframe = Variable('f_{frame}', '-',
                          'Fractional frame weight')  # [Philippe]
        flugg1 = Variable(
            'f_{lugg,1}', '-',
            'Proportion of passengers with one suitcase')  # [Philippe]
        flugg2 = Variable(
            'f_{lugg,2}', '-',
            'Proportion of passengers with two suitcases')  # [Philippe]
        fpadd = Variable('f_{padd}', 0.35, '-',
                         'Other misc weight as fraction of payload weight')
        fseat = Variable('f_{seat}', '-', 'Fractional seat weight')
        fstring = Variable('f_{string}', '-',
                           'Fractional stringer weight')  # [Philippe]

        # Weights
        Wapu = Variable('W_{apu}', 'lbf', 'APU weight')
        Wavgpass = Variable('W_{avg. pass}', 'lbf',
                            'Average passenger weight')  # [Philippe]
        Wavgpasstot = Variable(
            'W_{avg. pass_{total}}', 215., 'lbf',
            'Average passenger weight including payload')  #[TAS]
        Wcargo = Variable('W_{cargo}', 'lbf', 'Cargo weight')  # [Philippe]
        Wcarryon = Variable('W_{carry on}', 'lbf',
                            'Ave. carry-on weight')  # [Philippe]
        Wchecked = Variable('W_{checked}', 'lbf',
                            'Ave. checked bag weight')  # [Philippe]
        Wcone = Variable('W_{cone}', 'lbf', 'Cone weight')
        Wdb = Variable('W_{db}', 'lbf', 'Web weight')
        Wfix = Variable('W_{fix}', 'lbf',
                        'Fixed weights (pilots, cockpit seats, navcom)')
        Wfloor = Variable('W_{floor}', 'lbf', 'Floor weight')
        Wfuse = Variable('W_{fuse}', 'lbf', 'Fuselage weight')
        Winsul = Variable('W_{insul}', 'lbf', 'Insulation material weight')
        Wpadd = Variable('W_{padd}', 'lbf',
                         'Misc weights (galley, toilets, doors etc.)')
        Wseat = Variable('W_{seat}', 'lbf', 'Seating weight')
        Wshell = Variable('W_{shell}', 'lbf', 'Shell weight')
        Wskin = Variable('W_{skin}', 'lbf', 'Skin weight')
        Wtail = Variable('W_{tail}', 'lbf', 'Total tail weight')
        Wwindow = Variable('W_{window}', 'lbf', 'Window weight')

        with Vectorize(Nmissions):
            Wpay = Variable('W_{payload}', 'lbf', 'Payload weight')
            Wlugg = Variable('W_{lugg}', 'lbf', 'Passenger luggage weight')
            Wpass = Variable('W_{pass}', 'lbf', 'Passenger weight')
        Wpaymax = Variable('W_{payload_{max}}', 'lbf',
                           'Maximum payload weight')

        # x-location variables
        xshell1 = Variable('x_{shell1}', 'm', 'Start of cylinder section')
        xshell2 = Variable('x_{shell2}', 'm', 'End of cylinder section')
        xtail = Variable('x_{tail}', 'm', 'x-location of tail')
        xwing = Variable('x_{wing}', 'm', 'x-location of wing c/4')

        # Wingbox variables
        xf = Variable('x_f', 'm', 'x-location of front of wingbox')
        xb = Variable('x_b', 'm', 'x-location of back of wingbox')
        w = Variable('r_{w/c}', 0.5, '-', 'Wingbox width-to-chord ratio')

        #weight margin and sensitivity
        Cfuse = Variable('C_{fuse}', 1, '-',
                         'Fuselage Weight Margin and Sensitivity')

        #fuselage drag reference mach
        MfuseD = Variable('M_{fuseD}', '-', 'Fuselage Drag Reference Mach')

        # Moments
        # alphaMf0 = Variable('\\alpha_{Mf0}','-','AoA at which fuselage moment is zero')

        constraints = []
        with SignomialsEnabled():
            constraints.extend([
                # Passenger constraints
                Wlugg >= flugg2 * npass * 2 * Wchecked + flugg1 * npass * Wchecked + Wcarryon,
                TCS([Wpass >= npass * Wavgpass]),
                Wpay >= Wpass + Wlugg + Wcargo,
                TCS([Wpay >= npass * Wavgpasstot]),
                Wpaymax >= Wpay,
                nseat >= npass,
                nrows == nseat / SPR,
                lshell == nrows * pitch,

                # Fuselage joint angle relations
                thetadb == wdb / Rfuse,  # first order Taylor works...
                hdb >= Rfuse * (1.0 - .5 * thetadb**2),  # [SP]

                # Cross-sectional constraints
                Adb >= (2 * hdb + dRfuse) * tdb,
                Afuse >= (pi + 2 * thetadb + 2 * thetadb * \
                          (1 - thetadb**2 / 2)) * Rfuse**2 + 2*dRfuse*Rfuse,  # [SP]
                Askin >= (2 * pi + 4 * thetadb) * Rfuse * tskin + 2*dRfuse*tskin,
                wfloor == wfuse,
                wfuse <= (Rfuse + wdb),
                SignomialEquality(hfuse, Rfuse + 0.5*dRfuse), #[SP] #[SPEquality]
                TCS([tshell <= tskin * (1. + rE * fstring * rhoskin / rhobend)]), #[SP]

                # Fuselage surface area relations
                Snose >= (2 * pi + 4 * thetadb) * Rfuse**2 * \
                (1 / 3 + 2 / 3 * (lnose / Rfuse)**(8 / 5))**(5 / 8),
                Sbulk >= (2 * pi + 4 * thetadb) * Rfuse**2,

                # Fuselage length relations
                SignomialEquality(lfuse, lnose + lshell + lcone), #[SP] #[SPEquality]
                    # NOTE: it is not clear which direction the pressure is!
                lcone == Rfuse / lamcone,
                xshell1 == lnose,
                TCS([xshell2 >= lnose + lshell]),
                # STRESS RELATIONS
                # Pressure shell loading
                tskin == dPover * Rfuse / sigskin,
                tdb == 2 * dPover * wdb / sigskin,
                sigx == dPover * Rfuse / (2 * tshell),
                sigth == dPover * Rfuse / tskin,

                # Floor loading
                lfloor >= lshell + 2 * Rfuse,
                TCS([Pfloor >= Nland * (Wpaymax + Wseat)]),
                Afloor >= 2. * Mfloor / (sigfloor * hfloor) + 1.5 * Sfloor / taufloor,
                Vfloor == 2 * wfloor * Afloor,
                Wfloor >= rhofloor * g * Vfloor + 2 * wfloor * lfloor * Wppfloor,
                # hfloor <= 0.1 * Rfuse,

                # Tail cone sizing
                taucone == sigskin,
                Wcone >= rhocone * g * Vcone * (1 + fstring + fframe),
                xtail >= lnose + lshell + .5 * lcone,

                # BENDING MODEL
                # Maximum axial stress is the sum of bending and pressurization
                # stresses
                Ihshell <= ((pi + 4 * thetadb) * Rfuse**2 + 8.*(1-thetadb**2/2) * (dRfuse/2.)*Rfuse + \
                            (2*pi + 4 * thetadb)*(dRfuse/2)**2) * Rfuse * tshell + \
                    2 / 3 * (hdb + dRfuse/2.)**3 * tdb,  # [SP]
                Ivshell <= (pi*Rfuse**2 + 8*wdb*Rfuse + (2*pi+4*thetadb)*wdb**2)*Rfuse*tshell, #[SP] #Ivshell
                # approximation needs to be improved

                # Horizontal bending material model
                # Calculating xhbend, the location where additional bending
                # material is required
                xhbendLand >= xwing, xhbendLand <= lfuse,
                xhbendMLF >= xwing, xhbendMLF <= lfuse,

                SignomialEquality(A0h, A2hLand * (xshell2 - xhbendLand) ** 2 + A1hLand * (xtail - xhbendLand)), # [SP] #[SPEquality]
                SignomialEquality(A0h, A2hMLF * (xshell2 - xhbendMLF) ** 2 + A1hMLF * (xtail - xhbendMLF)), # [SP] #[SPEquality]

                A2hLand >= Nland * (Wpaymax + Wpadd + Wshell + Wwindow + Winsul + Wfloor + Wseat) / \
                (2 * lshell * hfuse * sigMh),  # Landing loads constant A2hLand
                A2hMLF >= Nlift * (Wpaymax + Wpadd + Wshell + Wwindow + Winsul + Wfloor + Wseat) / \
                (2 * lshell * hfuse * sigMh),  # Max wing aero loads constant A2hMLF

                # Shell inertia constant A0h
                A0h == (Ihshell / (rE * hfuse**2)), # [SP]

                # Bending area behind wingbox
                AhbendfLand >= A2hLand * (xshell2 - xf)**2 + A1hLand * (xtail - xf) - A0h, # [SP]
                AhbendfMLF >= A2hMLF * (xshell2 - xf)**2 + A1hMLF * (xtail - xf) - A0h, # [SP]

                # Bending area in front of wingbox
                AhbendbLand >= A2hLand * (xshell2 - xb)**2 + A1hLand * (xtail - xb) - A0h, # [SP]
                AhbendbMLF >= A2hMLF * (xshell2 - xb)**2 + A1hMLF * (xtail - xb) - A0h, # [SP]

                # Bending volume forward of wingbox
                Vhbendf >= A2hLand / 3 * ((xshell2 - xf)**3 - (xshell2 - xhbendLand)**3) \
                + A1hLand / 2 * ((xtail - xf)**2 - (xtail - xhbendLand)**2) \
                - A0h * (xhbendLand - xf),  # [SP]
                Vhbendf >= A2hMLF / 3 * ((xshell2 - xf)**3 - (xshell2 - xhbendMLF)**3) \
                + A1hMLF / 2 * ((xtail - xf)**2 - (xtail - xhbendMLF)**2) \
                - A0h * (xhbendMLF - xf),  # [SP]

                # Bending volume behind wingbox
                Vhbendb >= A2hLand / 3 * ((xshell2 - xb)**3 - (xshell2 - xhbendLand)**3) \
                + A1hLand / 2 * ((xtail - xb)**2 - (xtail - xhbendLand)**2) \
                - A0h * (xhbendLand - xb),  # [SP]
                Vhbendb >= A2hMLF / 3 * ((xshell2 - xb)**3 - (xshell2 - xhbendMLF)**3) \
                + A1hMLF / 2 * ((xtail - xb)**2 - (xtail - xhbendMLF)**2) \
                - A0h * (xhbendMLF - xb),  # [SP]

                # Bending volume over wingbox
                Vhbendc >= .5 * (AhbendfLand + AhbendbLand) * c0 * w,
                Vhbendc >= .5 * (AhbendfMLF + AhbendbMLF) * c0 * w,

                # Determining more constraining load case (landing vs. max aero horizontal bending)
                Vhbend >= Vhbendc + Vhbendf + Vhbendb,
                Whbend >= g * rhobend * Vhbend,

                # Vertical bending material model
                # Calculating xvbend, the location where additional bending material is required
                xvbend >= xwing, xvbend <= lfuse,
                SignomialEquality(B0v, B1v * (xtail - xvbend)), # [SP] #[SPEquality]
                #B1v definition in Aircraft()
                B0v == Ivshell/(rE*wfuse**2),
                Avbendb >= B1v * (xtail - xb) - B0v,
                Vvbendb >= 0.5*B1v * ((xtail-xb)**2 - (xtail - xvbend)**2) - B0v * (xvbend - xb),
                Vvbendc >= 0.5*Avbendb*c0*w,
                Vvbend >= Vvbendb + Vvbendc,
                Wvbend >= rhobend*g*Vvbend,

                # Wing variable substitutions
                SignomialEquality(xf,xwing + .5 * c0 * w), # [SP] [SPEquality]
                SignomialEquality(xb,xwing - .5 * c0 * w),  # [SP] [SPEquality]

                sigMh <= sigbend - rE * dPover / 2 * Rfuse / tshell,
                sigMv <= sigbend - rE * dPover / 2 * Rfuse / tshell,

                # Volume relations
                Vcyl == Askin * lshell,
                Vnose == Snose * tskin,
                Vbulk == Sbulk * tskin,
                Vdb == Adb * lshell,
                Vcabin >= Afuse * (lshell + 0.67 * lnose + 0.67 * Rfuse),

                # Weight relations
                Wapu == Wpaymax * fapu,
                Wdb == rhoskin * g * Vdb,
                Winsul >= Wppinsul * ((1.1 * pi + 2 * thetadb) * Rfuse * lshell + 0.55 * (Snose + Sbulk)),
                Wwindow >= Wpwindow * lshell,
                Wpadd == Wpaymax * fpadd,
                # Two methods for determining seat weight (must be inequalities)
                Wseat >= Wpseat * nseat,
                Wseat >= fseat * Wpaymax,

                Wskin >= rhoskin * g * (Vcyl + Vnose + Vbulk),
                Wshell >= Wskin * (1 + fstring + ffadd + fframe) + Wdb,
                Wfuse >= Cfuse*(Wshell + Wfloor + Winsul + \
                    Wapu + Wfix + Wwindow + Wpadd + Wseat + Whbend + Wvbend + Wcone),
            ])

        return constraints
Exemplo n.º 16
0
    def setup(self, Nclimb, Ncruise, Nfleet, substitutions=None, **kwargs):
        eng = 0

        #two level vectorization to make a fleet
        with Vectorize(Nfleet):
            # vectorize
            with Vectorize(Nclimb + Ncruise):
                enginestate = FlightState()

        ac = Aircraft(Nclimb, Ncruise, enginestate, eng, Nfleet)

        #two level vectorization to make a fleet
        with Vectorize(Nfleet):
            #Vectorize
            with Vectorize(Nclimb):
                climb = ClimbSegment(ac)

            with Vectorize(Ncruise):
                cruise = CruiseSegment(ac)

        statelinking = StateLinking(climb.state, cruise.state, enginestate,
                                    Nclimb, Ncruise)

        with Vectorize(Nfleet):
            #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')

            dhfthold = Variable('dhfthold', 'ft', 'Hold Variable')

        W_ffleet = Variable('W_{f_{fleet}}', 'N', 'Total Fleet Fuel Burn')

        h = climb['h']
        hftClimb = climb['hft']
        dhft = climb['dhft']
        hftCruise = cruise['hft']

        #make overall constraints
        constraints = []

        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 == CruiseAlt,
            TCS([
                hftClimb[1:Nclimb] >= hftClimb[:Nclimb - 1] + dhft[:Nclimb - 1]
            ]),
            TCS([hftClimb[0] >= dhft[0]]),
            hftClimb[-1] <= hftCruise,

            #compute the dh
            dhfthold == hftCruise[0] / Nclimb,
            dhft == dhfthold,

            #set the range for each cruise segment, doesn't take credit for climb
            #down range disatnce covered
            cruise.cruiseP['Rng'] == ReqRng / (Ncruise),

            #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],
            CruiseAlt >= 30000 * units('ft'),

            #min climb rate constraint
            climb['RC'] >= 500 * units('ft/min'),
        ])

        fleetfuel = [
            #compute the fleet fuel burn
            W_ffleet >= .375 * W_ftotal[0] + .375 * W_ftotal[1] +
            .125 * W_ftotal[2] + .125 * W_ftotal[3],
        ]

        M2 = .8
        M25 = .6
        M4a = .1025
        M0 = .8

        engineclimb = [
            ac.engine.engineP['M_2'][:Nclimb] == climb['M'],
            ac.engine.engineP['M_{2.5}'][:Nclimb] == 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}'][: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_{spec}'][:Nclimb]
            ]),
        ]

        M25 = .6

        enginecruise = [
            ac.engine.engineP['M_2'][Nclimb:] == cruise['M'],
            ac.engine.engineP['M_{2.5}'][Nclimb:] == M25,

            #steady level flight constraint on D
            cruise['D'] == ac['numeng'] * ac.engine['F_{spec}'][Nclimb:],

            #breguet range eqn
            TCS([
                cruise['z_{bre}'] >=
                (ac.engine['TSFC'][Nclimb:] * cruise['thr'] * cruise['D']) /
                cruise['W_{avg}']
            ]),
        ]

        ranges = [
            ReqRng[0] == 500 * units('nautical_miles'),
            ReqRng[1] == 1000 * units('nautical_miles'),
            ReqRng[2] == 1500 * units('nautical_miles'),
            ReqRng[3] == 2000 * units('nautical_miles'),
        ]

        return constraints + ac + climb + cruise + enginecruise + engineclimb + enginestate + statelinking + ranges + fleetfuel
Exemplo n.º 17
0
    def setup(self):

        #variables
        p       = Variable('p_{ht}', '-', 'Substituted variable = 1 + 2*taper')
        q       = Variable('q_{ht}', '-', 'Substituted variable = 1 + taper')
        etaht   = Variable('\\eta_{ht}', '-', 'Tail efficiency')
        tanLh   = Variable('\\tan(\\Lambda_{ht})', '-',
                           'tangent of horizontal tail sweep')
        taper   = Variable('\lambda_{ht}', '-', 'Horizontal tail taper ratio')
        tau     = Variable('\\tau_{ht}', '-',
                           'Horizontal tail thickness/chord ratio')
        xcght   = Variable('x_{CG_{ht}}', 'm', 'Horizontal tail CG location')
        ymac    = Variable('y_{\\bar{c}_{ht}}', 'm',
                           'Spanwise location of mean aerodynamic chord')
        dxlead  = Variable('\\Delta x_{lead_{ht}}', 'm',
                            'Distance from CG to horizontal tail leading edge')
        dxtrail = Variable('\\Delta x_{trail_{ht}}', 'm',
                            'Distance from CG to horizontal tail trailing edge')
        lht     = Variable('l_{ht}', 'm', 'Horizontal tail moment arm')
        ARht     = Variable('AR_{ht}', '-', 'Horizontal tail aspect ratio')
        amax    = Variable('\\alpha_{ht,max}', '-', 'Max angle of attack, htail')
        e       = Variable('e_{ht}', '-', 'Oswald efficiency factor')
        Sh      = Variable('S_{ht}', 'm^2', 'Horizontal tail area')
        bht     = Variable('b_{ht}', 'm', 'Horizontal tail span')
        chma    = Variable('\\bar{c}_{ht}', 'm', 'Mean aerodynamic chord (ht)')
        croot   = Variable('c_{root_{ht}}', 'm', 'Horizontal tail root chord')
        ctip    = Variable('c_{tip_{ht}}', 'm', 'Horizontal tail tip chord')
        Lmax    = Variable('L_{ht_{max}}', 'N', 'Maximum load')
        fl      = Variable(r"f(\lambda_{ht})", '-',
                           'Empirical efficiency function of taper')
        CLhmax  = Variable('C_{L_{ht,max}}', '-', 'Max lift coefficient')
        CLfCG = Variable('C_{L_{ht,fCG}}', '-', 'HT CL During Max Forward CG')

        #new variables
        Vh = Variable('V_{ht}', '-', 'Horizontal Tail Volume Coefficient')
        mrat = Variable('m_{ratio}', '-', 'Wing to Tail Lift Slope Ratio')
        #variable just for the D8
        cattach = Variable('c_{attach}', 'm', 'HT Chord Where it is Mounted to the VT')

        #constraints
        constraints = []

        with SignomialsEnabled():

            constraints.extend([
                # Moment arm and geometry -- same as for vtail
                TCS([dxlead + ymac * tanLh + 0.25 * chma >= lht], reltol=1e-2),  # [SP]
                TCS([dxlead + croot <= dxtrail]),
                p >= 1 + 2*taper,
                2*q >= 1 + p,
                ymac == (bht/3)*q/p,

                SignomialEquality((2./3)*(1 + taper + taper**2)*croot/q,
                     chma),
                taper == ctip/croot,
                SignomialEquality(Sh, bht*(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=0.2),
                # NOTE: slightly slack
                TCS([e*(1 + fl*ARht) <= 1]),

                ARht == bht**2/Sh,

                taper >= 0.2, # TODO: make less arbitrary
                taper <= 1,
                ])

        return constraints
Exemplo n.º 18
0
    def setup(self, ac, substitutions=None, **kwargs):
        #define the number of each flight segment
        Nclimb = 2
        Ncruise = 2

        #Vectorize
        with Vectorize(Nclimb):
            climb = ClimbSegment(ac)

        with Vectorize(Ncruise):
            cruise = CruiseSegment(ac)

        #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('R_{req}', 'nautical_miles', 'Required Cruise Range')

        h = climb['h']
        hftClimb = climb['hft']
        dhft = climb['dhft']
        hftCruise = cruise['hft']

        #make overall constraints
        constraints = []

        constraints.extend([
            #weight constraints
            TCS([
                ac['W_{e}'] + ac['W_{payload}'] + W_ftotal +
                ac['numeng'] * ac['W_{engine}'] + ac['W_{wing}'] <= 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([
                ac['W_{e}'] + ac['W_{payload}'] +
                ac['numeng'] * ac['W_{engine}'] + ac['W_{wing}'] <=
                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 == CruiseAlt,
            TCS([hftClimb[1:Ncruise] >= hftClimb[:Ncruise - 1] + dhft]),
            TCS([hftClimb[0] >= dhft[0]]),
            hftClimb[-1] <= hftCruise,

            #compute the dh
            dhft == hftCruise / Nclimb,

            #constrain the thrust
            climb['thrust'] <= 2 * max(cruise['thrust']),

            #set the range for each cruise segment, doesn't take credit for climb
            #down range disatnce covered
            cruise.cruiseP['Rng'] == ReqRng / (Ncruise),

            #set the TSFC
            climb['TSFC'] == .7 * units('1/hr'),
            cruise['TSFC'] == .5 * units('1/hr'),
        ])

        # Model.setup(self, W_ftotal + s*units('N'), constraints + ac + climb + cruise, subs)
        return constraints + ac + climb + cruise
    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
Exemplo n.º 20
0
    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
Exemplo n.º 21
0
    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
Exemplo n.º 22
0
    def setup(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')
        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')
        Clg = Variable('C_{lg}', 1, '-', 'Landing Gear Weight Margin/Sens Factor')
        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_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')
        xcglg   = Variable('x_{CG_{lg}}', 'm', 'Landing gear CG')
        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')

        d_nac   = Variable('d_{nacelle}', 'm', 'Nacelle diameter')

        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

                           # Longitudinal tip over (static)
                           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]

                           # Size/Volume for retraction
                           y_m >= l_m,

                           # 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 >= Clg * (W_mg + W_ng),

                           #LG CG accounting
                           TCS([W_lg*xcglg >= W_ng*x_n + W_mg*x_m], reltol=1E-2,
                                raiseerror=False),
                           x_m >= xcglg,
                          ]

        return constraints
Exemplo n.º 23
0
    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
Exemplo n.º 24
0
    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
Exemplo n.º 25
0
    def setup(self, substitutions=None, **kwargs):
        eng = 0
        #define the number of each flight segment
        Ncruise = 2

        # vectorize
        with Vectorize(Ncruise):
            enginestate = FlightState()

        ac = Aircraft(0, Ncruise, enginestate, eng)

        #Vectorize
        with Vectorize(Ncruise):
            cruise = CruiseSegment(ac)

        statelinking = StateLinking(cruise.state, enginestate, Ncruise)

        #declare new variables
        W_ftotal = Variable('W_{f_{total}}', 'N', 'Total Fuel Weight')
        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')

        hftCruise = cruise['hft']

        #make overall constraints
        constraints = []

        constraints.extend([
            #weight constraints
            TCS([
                ac['W_{e}'] + ac['W_{payload}'] + W_ftotal +
                ac['numeng'] * ac['W_{engine}'] + ac['W_{wing}'] <= W_total
            ]),
            cruise['W_{start}'][0] == W_total,
            TCS([
                cruise['W_{start}'] >= cruise['W_{end}'] + cruise['W_{burn}']
            ]),
            cruise['W_{start}'][1:] == cruise['W_{end}'][:-1],
            TCS([
                ac['W_{e}'] + ac['W_{payload}'] +
                ac['numeng'] * ac['W_{engine}'] + ac['W_{wing}'] <=
                cruise['W_{end}'][-1]
            ]),
            TCS([W_ftotal >= W_fcruise]),
            TCS([W_fcruise >= sum(cruise['W_{burn}'])]),

            #altitude constraints
            hftCruise == CruiseAlt,
            CruiseAlt >= 30000 * units('ft'),

            #set the range for each cruise segment, doesn't take credit for climb
            #down range disatnce covered
            cruise.cruiseP['Rng'] == ReqRng / (Ncruise),

            #compute fuel burn from TSFC
            cruise['W_{burn}'] == ac['numeng'] * ac.engine['TSFC'] *
            cruise['thr'] * ac.engine['F'],
        ])

        M2 = .8
        M25 = .6
        M4a = .1025
        M0 = .8

        enginecruise = [
            ac.engine.engineP['M_2'][0] == cruise['M'][0],
            ac.engine.engineP['M_2'][1] == cruise['M'][1],
            ac.engine.engineP['M_{2.5}'][1] == M25,
            ac.engine.engineP['M_{2.5}'][0] == 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,

            #steady level flight constraint on D
            cruise['D'] == ac['numeng'] * ac.engine['F'],

            #breguet range eqn
            TCS([
                cruise['z_{bre}'] >=
                (ac.engine['TSFC'] * cruise['thr'] * cruise['D']) /
                cruise['W_{avg}']
            ]),
        ]

        # Model.setup(self, W_ftotal + s*units('N'), constraints + ac + climb + cruise, subs)
        return constraints + ac + cruise + enginecruise + enginestate + statelinking
Exemplo n.º 26
0
    def setup(self, surface, surfacetype):
        # Variables
        Icap = Variable('I_{cap}', '-',
                        'Non-dim spar cap area moment of inertia')
        Mr = Variable('M_r', 'N', 'Root moment per root chord')
        nu = Variable('\\nu', '-', 'Dummy variable = $(t^2 + t + 1)/(t+1)^2$')
        Wcap = Variable('W_{cap}', 'N', 'Weight of spar caps')
        Wweb = Variable('W_{web}', 'N', 'Weight of shear web')
        Wstruct = Variable('W_{struct}', 'N', 'Structural weight')

        # Constants
        g = Variable('g', 9.81, 'm/s^2', 'Gravitational acceleration')
        Nlift = Variable('N_{lift}', '-', 'Wing loading multiplier')
        rh = Variable('r_h', 0.75, '-',
                      'Fractional wing thickness at spar web')
        rhocap = Variable('\\rho_{cap}', 2700, 'kg/m^3',
                          'Density of spar cap material')
        rhoweb = Variable('\\rho_{web}', 2700, 'kg/m^3',
                          'Density of shear web material')
        sigmax = Variable('\\sigma_{max}', 250e6, 'Pa',
                          'Allowable tensile stress')
        sigmaxshear = Variable('\\sigma_{max,shear}', 167e6, 'Pa',
                               'Allowable shear stress')
        wwb = Variable('r_{w/c}', 0.5, '-', 'Wingbox width-to-chord ratio')
        tcap = Variable('t_{cap}', '-', 'Non-dim. spar cap thickness')
        tweb = Variable('t_{web}', '-', 'Non-dim. shear web thickness')

        objective = Wstruct

        if surfacetype == "wing":
            taper = Variable('taper', '-', 'Taper ratio')
            AR = surface['AR']
            b = surface['b']
            S = surface['S']
            p = surface['p']
            q = surface['q']
            tau = surface['\\tau']
            tau_max = surface['\\tau_{max_w}']
            Lmax = surface['L_{max}']
        elif surfacetype == "vertical_tail":
            taper = Variable('taper', '-', 'Taper ratio')
            #factors of 2 required since the VT is only half span and the wing model
            #is for a full span wing
            AR = Variable('AR_{vt}', '-',
                          'Vertical tail aspect ratio (double span)')
            b = 2. * surface['b_{vt}']
            S = 2. * surface['S_{vt}']
            p = surface['p_{vt}']
            q = surface['q_{vt}']
            tau = surface['\\tau_{vt}']
            Lmax = 2. * surface['L_{vt_{max}}']
            taper = surface['\\lambda_{vt}']
        elif surfacetype == "horizontal_tail":
            taper = Variable('taper', 0.3, '-', 'Taper ratio')
            AR = surface['AR_{ht}']
            b = surface['b_{ht}']
            S = surface['S_{ht}']
            p = surface['p_{ht}']
            q = surface['q_{ht}']
            tau = surface['\\tau_{ht}']
            Lmax = surface['L_{ht_{max}}']

            # Pi tail sizing variables
            # Splits the max lift into triangular and rectangular components
            # for root bending sizing.
            bhtout = Variable('b_{ht_{out}}', 'm',
                              'Horizontal tail outboard half-span')
            Lhtri = Variable('L_{ht_{tri}}', 'N', 'Triangular HT load')
            Lhrect = Variable('L_{ht_{rect}}', 'N', 'Rectangular HT load')
            Lhtriout = Variable('L_{ht_{tri_{out}}}', 'N',
                                'Triangular HT load outboard')
            Lhrectout = Variable('L_{ht_{rect_{out}}}', 'N',
                                 'Rectangular HT load outboard')
            Mrout = Variable('M_{r_{out}}', 'N',
                             'Wing moment at pin joint ')  #TODO
            Lshear = Variable('L_{shear}', 'N',
                              'Maximum shear load (at pin joint)')
            piMfac = Variable('\\pi_{M-fac}', '-',
                              'Pi-tail bending structural factor')

        constraints = [
            # Aspect ratio definition
            AR == b**2 / S,

            # Root stiffness (see Hoburg 2014)
            # Assumes rh = 0.75, so that rms box height = ~0.92*tmax
            TCS([
                0.92 * wwb * tau * tcap**2 + Icap <=
                0.92**2 / 2 * wwb * tau**2 * tcap
            ]),

            # Posynomial approximation of nu=(1+lam+lam^2)/(1+lam)^2
            nu**3.94 >= 0.86 * p**(-2.38) + 0.14 * p**0.56,  # Woody's fit

            # Weight of spar caps and shear webs
            Wweb >= 8 * rhoweb * g * rh * tau * tweb * S**1.5 * nu /
            (3 * AR**0.5),
        ]

        if surfacetype == "wing":
            constraints += [
                # Upper bound on maximum thickness
                tau <= tau_max,
                Wstruct >= (Wweb + Wcap),
                # Shear web sizing
                # Assumes all shear loads are carried by web and rh=0.75
                TCS([12 >= AR * Lmax * q**2 / (tau * S * tweb * sigmaxshear)]),
                # Weight of spar caps and shear webs
                Wcap >= 8 * rhocap * g * wwb * tcap * S**1.5 * nu /
                (3 * AR**0.5),
                Nlift == 3,
                # Stress limit
                # Assumes bending stress carried by caps (Icap >> Iweb)
                TCS([8 >= Mr * AR * q**2 * tau / (S * Icap * sigmax)]),
            ]
        elif surfacetype == "vertical_tail":
            constraints += [
                # Upper bound on maximum thickness
                tau <= 0.14,
                Wstruct >= 0.5 * (Wweb + Wcap),
                # Root moment calculation (see Hoburg 2014)
                # Assumes lift per unit span proportional to local chord
                Mr >= Lmax * AR * p / 24,
                # Shear web sizing
                # Assumes all shear loads are carried by web and rh=0.75
                TCS([
                    12 >= AR * Lmax * Nlift * q**2 /
                    (tau * S * tweb * sigmaxshear)
                ]),
                # Weight of spar caps and shear webs
                Wcap >= 8 * rhocap * g * wwb * tcap * S**1.5 * nu /
                (3 * AR**0.5),
                Nlift == 1,
                # Stress limit
                # Assumes bending stress carried by caps (Icap >> Iweb)
                TCS([8 >= Nlift * Mr * AR * q**2 * tau / (S * Icap * sigmax)]),
            ]
        elif surfacetype == "horizontal_tail":
            constraints += [
                # Upper bound on maximum thickness
                tau <= 0.14,
                Wstruct >= (Wweb + Wcap),
                Lhtriout >= Lhtri * bhtout**2 / (0.5 * b)**2,
                Lhrectout >= Lhrect * bhtout / (0.5 * b),
                12 >= 2 * AR * Lshear * Nlift * q**2 /
                (tau * S * tweb * sigmaxshear),  #TODO
                Wcap >= piMfac * 8 * rhocap * g * wwb * tcap * S**1.5 * nu /
                (3 * AR**0.5),  #TODO
                Nlift == 1,
                # Stress limit
                # Assumes bending stress carried by caps (Icap >> Iweb)
                TCS([8 >= Nlift * Mr * AR * q**2 * tau / (S * Icap * sigmax)]),
            ]

        return constraints