def test_sigeq(self): x = Variable("x") y = VectorVariable(1, "y") c = Variable("c") # test left vector input to sigeq with SignomialsEnabled(): m = Model(c, [ c >= (x + 0.25)**2 + (y - 0.5)**2, SignomialEquality(x**2 + x, y) ]) sol = m.localsolve(solver=self.solver, verbosity=0, mutategp=False) self.assertAlmostEqual(sol("x"), 0.1639472, self.ndig) self.assertAlmostEqual(sol("y")[0], 0.1908254, self.ndig) self.assertAlmostEqual(sol("c"), 0.2669448, self.ndig) # test right vector input to sigeq with SignomialsEnabled(): m = Model(c, [ c >= (x + 0.25)**2 + (y - 0.5)**2, SignomialEquality(y, x**2 + x) ]) sol = m.localsolve(solver=self.solver, verbosity=0) self.assertAlmostEqual(sol("x"), 0.1639472, self.ndig) self.assertAlmostEqual(sol("y")[0], 0.1908254, self.ndig) self.assertAlmostEqual(sol("c"), 0.2669448, self.ndig) # test scalar input to sigeq y = Variable("y") with SignomialsEnabled(): m = Model(c, [ c >= (x + 0.25)**2 + (y - 0.5)**2, SignomialEquality(x**2 + x, y) ]) sol = m.localsolve(solver=self.solver, verbosity=0) self.assertAlmostEqual(sol("x"), 0.1639472, self.ndig) self.assertAlmostEqual(sol("y"), 0.1908254, self.ndig) self.assertAlmostEqual(sol("c"), 0.2669448, self.ndig)
def setup(self): # Env. constants alt_top = Variable('h_{top}', 10000, 'm', 'highest altitude valid') #a_MSL = Variable('a_{MSL}',340.20,'m/s','Speed of sound at MSL') mu_MSL = Variable('\\mu_{MSL}', 1.778e-5, "kg/m/s", 'dynamic viscosity at MSL', pr=4.) #nu_MSL = Variable('\\nu_{MSL}', 1.4524e-5, 'm^2/s', 'kinematic viscosity at MSL') #T_MSL = Variable('T_{MSL}', 288.19, 'K', 'temperature at MSL') rho_MSL = Variable("\\rho_{MSL}", 1.2256, "kg/m^3", "density of air at MSL", pr=5.) #p_MSL = Variable('P_{MSL}', 101308, 'Pa', 'pressure at MSL') alt = Variable('h', 'm', 'altitude') #a = Variable('a','m/s','Speed of sound') mu = Variable('\\mu', "kg/m/s", 'dynamic viscosity', pr=4.) #nu = Variable('\\nu', 'm^2/s', 'kinematic viscosity') #p = Variable('P', 'Pa', 'pressure') #T = Variable('T', 'K', 'temperature ') rho = Variable("\\rho", "kg/m^3", "density of air", pr=5.) # Defining ratios needed for constraints alt_rat = alt / alt_top #a_rat = a/a_MSL mu_rat = mu / mu_MSL #nu_rat = nu/nu_MSL #p_rat = p/p_MSL rho_rat = rho / rho_MSL #T_rat = T/T_MSL constraints = [] with SignomialsEnabled(): constraints += [ alt <= alt_top, #a_rat ** -0.0140 >= 1.00 * (alt_rat) ** 1.20e-05 + 0.00173 * (alt_rat) ** 1.13, SignomialEquality( mu_rat**-0.00795, 1.00 * (alt_rat)**1.33e-05 + 0.00156 * (alt_rat)**1.17), #nu_rat ** 0.00490 >= 1.00 * (alt_rat) ** 1.67e-05,# + 0.00424 * (alt_rat) ** 1.10, #p_rat ** -0.00318 >= 1.00 * (alt_rat) ** 2.18e-05,# + 0.00416 * (alt_rat) ** 1.12, SignomialEquality( rho_rat**-0.00336, 1.00 * (alt_rat)**1.72e-05 + 0.00357 * (alt_rat)**1.11), #T_rat ** -0.00706 >= 1.00 * (alt_rat) ** 1.21e-05,# + 0.00173 * (alt_rat) ** 1.13, ] return constraints
def setup(self, engine, state): self.engine = engine # Dimensional constants # Free variables BSFC = Variable("BSFC", "lbf/(hp*hr)", "brake specific fuel consumption") P_shaft = Variable("P_{shaft}", "kW", "shaft power") P_shaft_alt = Variable("P_{shaft,alt}", "kW", 'maximum shaft power at altitude') Thrust = Variable("T", "N", "propeller thrust") L = Variable("L", "-", "power lapse percentage") constraints = [] with SignomialsEnabled(): constraints += [ P_shaft <= P_shaft_alt, L == (0.937 * (state['h'] / self.engine['h_{ref}'])**0.0922)**10, SignomialEquality( 1, L + P_shaft_alt / self.engine['P_{shaft,max}']), (BSFC / self.engine['BSFC_{ref}'])**(0.1) >= 0.984 * (P_shaft / P_shaft_alt)**-0.0346, BSFC / self.engine['BSFC_{ref}'] >= 1., ] return constraints
def test_sigeq(self): x = Variable("x") y = VectorVariable(1, "y") # test vector input to sigeq c = Variable("c") with SignomialsEnabled(): m = Model(c, [c >= (x + 0.25)**2 + (y - 0.5)**2, SignomialEquality(x**2 + x, y)]) sol = m.localsolve(verbosity=0) self.assertAlmostEqual(sol("x"), 0.1639472, self.ndig) self.assertAlmostEqual(sol("y"), 0.1908254, self.ndig) self.assertAlmostEqual(sol("c"), 0.2669448, self.ndig)
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
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
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
def setup(self, aircraft, Nsegments): self.aircraft = aircraft W_f_m = Variable('W_{f_m}', 'N', 'total mission fuel') t_m = Variable('t_m', 'hr', 'total mission time') with Vectorize(Nsegments): Wavg = Variable('W_{avg}', 'N', 'segment average weight') Wstart = Variable('W_{start}', 'N', 'weight at the beginning of flight segment') Wend = Variable('W_{end}', 'N', 'weight at the end of flight segment') h = Variable('h', 'm', 'final segment flight altitude') havg = Variable('h_{avg}', 'm', 'average segment flight altitude') dhdt = Variable('\\frac{dh}{dt}', 'm/hr', 'climb rate') W_f_s = Variable('W_{f_s}', 'N', 'segment fuel burn') t_s = Variable('t_s', 'hr', 'time spent in flight segment') R_s = Variable('R_s', 'km', 'range flown in segment') state = Atmosphere() self.aircraftP = self.aircraft.dynamic(state) # Mission variables hcruise = Variable('h_{cruise_m}', 'm', 'minimum cruise altitude') Range = Variable("Range_m", "km", "aircraft range") W_p = Variable("W_{p_m}", "N", "payload weight", pr=20.) V_min = Variable("V_{min_m}", "m/s", "takeoff speed", pr=20.) TOfac = Variable('T/O factor_m', '-', 'takeoff thrust factor') cost_index = Variable("C_m", '1/hr', 'hourly cost index') constraints = [] # Setting up the mission with SignomialsEnabled(): constraints += [ havg == state['h'], # Linking states h[1:Nsegments - 1] >= hcruise, # Adding minimum cruise altitude # Weights at beginning and end of mission Wstart[0] >= W_p + self.aircraft.wing['W_w'] + self.aircraft.engine['W_e'] + W_f_m, Wend[Nsegments - 1] >= W_p + self.aircraft.wing['W_w'] + self.aircraft.engine['W_e'], # Lift, and linking segment start and end weights Wavg <= 0.5 * state['\\rho'] * self.aircraft['S'] * self.aircraftP.wingP['C_L'] * self.aircraftP['V']**2, Wstart >= Wend + W_f_s, # Making sure fuel gets burnt! Wstart[1:Nsegments] == Wend[:Nsegments - 1], Wavg == Wstart**0.5 * Wend**0.5, # Altitude changes h[0] == t_s[0] * dhdt[0], # Starting altitude dhdt >= 1. * units('m/hr'), havg[0] == 0.5 * h[0], havg[1:Nsegments] == (h[1:Nsegments] * h[0:Nsegments - 1])**(0.5), SignomialEquality( h[1:Nsegments], h[:Nsegments - 1] + t_s[1:Nsegments] * dhdt[1:Nsegments]), # Thrust and fuel burn W_f_s >= self.aircraftP.engineP['BSFC'] * self.aircraftP.engineP['P_{shaft}'] * t_s, self.aircraftP.engineP['T'] * self.aircraftP['V'] >= self.aircraftP['D'] * self.aircraftP['V'] + Wavg * dhdt, # Max MSL thrust at least 2*climb thrust self.aircraft.engine['P_{shaft,max}'] >= TOfac * self.aircraftP.engineP['P_{shaft}'][0], # Flight time t_s == R_s / self.aircraftP['V'], # Aggregating segment variables self.aircraft['W_f'] >= W_f_m, R_s == Range / Nsegments, # Dividing into equal range segments W_f_m >= sum(W_f_s), t_m >= sum(t_s) ] # Maximum takeoff weight constraints += [ self.aircraft['W'] >= W_p + self.aircraft.wing['W_w'] + self.aircraft['W_f'] + self.aircraft.engine['W_e'] ] # Stall constraint constraints += [ self.aircraft['W'] <= 0.5 * state['\\rho'] * self.aircraft['S'] * self.aircraft['C_{L,max}'] * V_min**2 ] # Wing weight model constraints += [ self.aircraft.wing['W_{w_{strc}}']**2. >= self.aircraft.wing['W_{w_{coeff1}}']**2. / self.aircraft.wing['\\tau']**2. * (self.aircraft.wing['N_{ult}']**2. * self.aircraft.wing['A']**3. * ((W_p + self.aircraft.fuse['V_{f_{fuse}}'] * self.aircraft['g'] * self.aircraft['\\rho_f']) * self.aircraft['W'] * self.aircraft.wing['S'])) ] # Upper bounding variables constraints += [ t_m <= 100000 * units('hr'), W_f_m <= 1e10 * units('N') ] return constraints, state, self.aircraft, self.aircraftP
def setup(self, combustor, engine, state, mixing=True): self.combustor = combustor self.engine = engine R = Variable('R', 287, 'J/kg/K', 'Air Specific Heat') #define new variables #--------------------------combustor exit (station 4) stagnation states------------------ Pt4 = Variable('P_{t_4}', 'kPa', 'Stagnation Pressure at the Combustor Exit (4)') ht4 = Variable('h_{t_4}', 'J/kg', 'Stagnation Enthalpy at the Combustor Exit (4)') Tt4 = Variable('T_{t_4}', 'K', 'Combustor Exit (Station 4) Stagnation Temperature') #--------------------High Pressure Turbine inlet state variables (station 4.1)------------------------- Pt41 = Variable('P_{t_{4.1}}', 'kPa', 'Stagnation Pressure at the Turbine Inlet (4.1)') Tt41 = Variable('T_{t_{4.1}}', 'K', 'Stagnation Temperature at the Turbine Inlet (4.1)') ht41 = Variable('h_{t_{4.1}}', 'J/kg', 'Stagnation Enthalpy at the Turbine Inlet (4.1)') u41 = Variable('u_{4.1}', 'm/s', 'Flow Velocity at Station 4.1') T41 = Variable('T_{4.1}', 'K', 'Static Temperature at the Turbine Inlet (4.1)') #------------------------Variables for cooling flow model--------------------------- # define the (f+1) variable, limits the number of signomials # for station 4a u4a = Variable('u_{4a}', 'm/s', 'Flow Velocity at Station 4a') M4a = Variable('M_{4a}', .1025, '-', 'User Specified Station 4a Mach #') P4a = Variable('P_{4a}', 'kPa', 'Static Pressure at Station 4a (4a)') uc = Variable('u_c', 'm/s', 'Cooling Airflow Speed at Station 4a') #---------------------------fuel flow fraction f-------------------------------- f = Variable('f', '-', 'Fuel Air Mass Flow Fraction') fp1 = Variable('fp1', '-', 'f + 1') #make the constraints constraints = [] with SignomialsEnabled(): #combustor constraints constraints.extend([ #flow through combustor ht4 == self.combustor['C_{p_{c}}'] * Tt4, #compute the station 4.1 enthalpy ht41 == self.combustor['C_{p_{c}}'] * Tt41, # making f+1 GP compatible --> needed for convergence SignomialEquality(fp1, f + 1), # Tight([fp1 <= f+1]), # Relaxation of this SE makes problem hit iteration limit ]) #mixing constraints if mixing: constraints.extend([ fp1 * u41 == (u4a * (fp1) * self.combustor['\\alpha_c'] * uc)**.5, #this is a stagnation relation, loosened SigEq # SignomialEquality(T41, Tt41-.5*(u41**2)/self.combustor['C_{p_{c}}']), T41 <= Tt41 - .5 * (u41**2) / self.combustor['C_{p_{c}}'], #here we assume no pressure loss in mixing so P41=P4a Pt41 == P4a * (Tt41 / T41)**(self.combustor.ccexp1), #compute station 4a quantities, assumes a gamma value of 1.313 (air @ 1400K) u4a == M4a * ((1.313 * R * Tt4)**.5) / self.combustor['hold_{4a}'], uc == self.combustor['r_{uc}'] * u4a, P4a == Pt4 * self.combustor['hold_{4a}']**(self.combustor.ccexp2), ]) #combustor constraints with no mixing else: constraints.extend([ Pt41 == Pt4, Tt41 == Tt4, ]) return constraints