def setup(self, static, Wcent): Nmax = Variable("N_{max}", 5, "-", "max loading") cbar, _ = c_bar(0.5, static.N) sigmaai = Variable("\\sigma_{AI}", 207, "MPa", "aluminum max stress") kappa = Variable("\\kappa", 0.05, "-", "max tip deflection ratio") with Vectorize(static.N - 1): Mr = Variable("M_r", "N*m", "wing section root moment") with Vectorize(static.N): qbar = Variable("\\bar{q}", cbar, "-", "normalized loading") beam = Beam(static.N, qbar) constraints = [ # dimensionalize moment of inertia and young's modulus beam["\\bar{EI}"] <= (8 * static["E"] * static["I"] / Nmax / Wcent / static["b"]**2), Mr == (beam["\\bar{M}"][:-1] * Wcent * Nmax * static["b"] / 4), sigmaai >= Mr / static["S_y"], beam["\\bar{\\delta}"][-1] <= kappa, ] return beam, constraints
def setup(self, N, qbar): with Vectorize(N - 1): EIbar = Variable("\\bar{EI}", "-", "normalized YM and moment of inertia") with Vectorize(N): Sbar = Variable("\\bar{S}", "-", "normalized shear") Mbar = Variable("\\bar{M}", "-", "normalized moment") th = Variable("\\theta", "-", "deflection slope") dbar = Variable("\\bar{\\delta}", "-", "normalized displacement") Sbartip = Variable("\\bar{S}_{tip}", 1e-10, "-", "Tip loading") Mbartip = Variable("\\bar{M}_{tip}", 1e-10, "-", "Tip moment") throot = Variable("\\theta_{root}", 1e-10, "-", "Base angle") dbarroot = Variable("\\bar{\\delta}_{root}", 1e-10, "-", "Base deflection") dx = Variable("dx", "-", "normalized length of element") constraints = [ Sbar[:-1] >= Sbar[1:] + 0.5 * dx * (qbar[:-1] + qbar[1:]), Sbar[-1] >= Sbartip, Mbar[:-1] >= Mbar[1:] + 0.5 * dx * (Sbar[:-1] + Sbar[1:]), Mbar[-1] >= Mbartip, th[0] >= throot, th[1:] >= th[:-1] + 0.5 * dx * (Mbar[1:] + Mbar[:-1]) / EIbar, dbar[0] >= dbarroot, dbar[1:] >= dbar[:-1] + 0.5 * dx * (th[1:] + th[:-1]), 1 == (N - 1) * dx, ] return constraints
def setup(self, aircraft, N=5, altitude=15000): Wfuelfs = Variable("W_{fuel-fs}", "lbf", "flight segment fuel weight") self.aircraft = aircraft with Vectorize(N): W = Variable("W", "lbf", "aircraft weight during flight segment") Wstart = Variable("W_{start}", "lbf", "vector-begin weight") Wend = Variable("W_{end}", "lbf", "vector-end weight") self.fs = FlightState(altitude) self.aircraftPerf = self.aircraft.flight_model(self.fs) self.slf = SteadyLevelFlight(W, self.fs, self.aircraft, self.aircraftPerf) self.br = BreguetRange(Wstart, Wend, self.aircraftPerf) self.submodels = [self.fs, self.aircraftPerf, self.slf, self.br] self.constraints = [ Wfuelfs >= self.br["W_{fuel}"].sum(), W == (Wstart * Wend)**0.5 ] if N > 1: self.constraints.extend([Wend[:-1] >= Wstart[1:]]) return self.aircraft, self.submodels, self.constraints
def setup(self, aircraft, N, altitude=15000, latitude=45, percent=90, day=355, dh=15000): fs = FlightSegment(aircraft, N, altitude, latitude, percent, day) with Vectorize(N): hdot = Variable("\\dot{h}", "ft/min", "Climb rate") deltah = Variable("\\Delta_h", dh, "ft", "altitude difference") hdotmin = Variable("\\dot{h}_{min}", 100, "ft/min", "minimum climb rate") constraints = [ hdot * fs.be["t"] >= deltah / N, hdot >= hdotmin, fs.slf["T"] >= (0.5 * fs["\\rho"] * fs["V"]**2 * fs["C_D"] * fs.aircraft.wing["S"] + fs["W_{start}"] * hdot / fs["V"]), ] return fs, constraints
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
def setup(self, nt): exec parse_variables(Rocket.__doc__) self.nt = nt self.nozzle = Nozzle() with Vectorize(nt): self.nozzlePerformance = NozzlePerformance(self.nozzle) constraints = [] return constraints, self.nozzle, self.nozzlePerformance
def setup(self, N): with Vectorize(N - 1): EIbar = self.EIbar = Variable( "\\bar{EI}", "-", "normalized YM and moment of inertia") dx = self.dx = Variable("dx", "-", "normalized length of element") with Vectorize(N): Sbar = Variable("\\bar{S}", self.SbarFun, "-", "normalized shear") Mbar = Variable("\\bar{M}", self.MbarFun, "-", "normalized moment") th = Variable("\\theta", "-", "deflection slope") dbar = Variable("\\bar{\\delta}", "-", "normalized displacement") self.dbar_tip = dbar[-1] throot = Variable("\\theta_{root}", 1e-10, "-", "Base angle") dbarroot = Variable("\\bar{\\delta}_{root}", 1e-10, "-", "Base deflection") constraints = [] if self.SbarFun is None: with Vectorize(N): qbar = self.qbar = Variable("\\bar{q}", self.qbarFun, "-", "normalized loading") Sbartip = Variable("\\bar{S}_{tip}", 1e-10, "-", "Tip loading") constraints.extend([ Sbar[:-1] >= Sbar[1:] + 0.5 * dx * (qbar[:-1] + qbar[1:]), Sbar[-1] >= Sbartip ]) if self.MbarFun is None: Mbartip = Variable("\\bar{M}_{tip}", 1e-10, "-", "Tip moment") constraints.extend([ Mbar[:-1] >= Mbar[1:] + 0.5 * dx * (Sbar[:-1] + Sbar[1:]), Mbar[-1] >= Mbartip ]) constraints.extend([ th[0] >= throot, th[1:] >= th[:-1] + 0.5 * dx * (Mbar[1:] + Mbar[:-1]) / EIbar, dbar[0] >= dbarroot, dbar[1:] >= dbar[:-1] + 0.5 * dx * (th[1:] + th[:-1]), ]) return constraints
def setup(self, nt, nx): exec parse_variables(Rocket.__doc__) self.nt = nt self.nx = nx self.nozzle = Nozzle() with Vectorize(nt): self.nozzlePerformance = NozzlePerformance(self.nozzle) self.section = SRM(nx) constraints = [ # Limiting nozzle size to cross-sectional area # self.nozzle.A_e <= np.pi*r**2, # Equal time segments self.section.dt == t_T/nt, # All fuel is consumed self.section.A_p_out[:,-1] == 1e-20*np.ones(nx)*np.pi*r**2, A_fuel == self.section.A_p_in[:,0], T_target == self.nozzlePerformance.T, c_T == self.nozzlePerformance.c_T, # Fuel parameters self.section.k_comb_p == k_comb_p, self.section.rho_p == rho_p, ] for i in range(nt-1): constraints += [ # Decreasing fuel self.section.A_p_out[:, i] == self.section.A_p_in[:, i+1], # Decreasing sectional area self.section.A_in[:,i] <= self.section.A_in[:,i+1], self.section.A_out[:,i] <= self.section.A_out[:,i+1], ] for i in range(nt): constraints += [ # Rocket length is section length, self.section.radius[i] == r, self.section.l[i] == l, # Matching nozzle and section conditions self.nozzlePerformance.mdot[i] == self.section.mdot_out[i], self.nozzlePerformance.T_t[i] == self.section.T_t_out[i], # Maximum chamber pressure self.section.P_chamb[:, i] <= P_max, self.nozzlePerformance.P_star[i] <= P_max, ] with SignomialsEnabled(): constraints += [ # Matching nozzle stagnation pressure Tight([self.nozzlePerformance.P_t[i] <= s[i]*(self.section.P_out[i] + 0.5*self.section.rho_out[i]*self.section.u_out[i]**2)], name='PtNozzle', printwarning=True), s[i]*self.nozzlePerformance.P_t[i] >= self.section.P_out[i] + 0.5*self.section.rho_out[i]*self.section.u_out[i]**2, s[i] >= 1 ] return constraints, self.nozzle, self.nozzlePerformance, self.section
def setup(self, aircraft): with Vectorize(4): # four flight segments fs = FlightSegment(aircraft) Wburn = fs.aircraftp["W_{burn}"] Wfuel = fs.aircraftp["W_{fuel}"] self.takeoff_fuel = Wfuel[0] return fs, [ Wfuel[:-1] >= Wfuel[1:] + Wburn[:-1], Wfuel[-1] >= Wburn[-1] ]
def setup(self, aircraft): self.aircraft = aircraft with Vectorize(4): # four flight segments self.fs = FlightSegment(aircraft) Wburn = self.fs.aircraftp.Wburn Wfuel = self.fs.aircraftp.Wfuel self.takeoff_fuel = Wfuel[0] return self.fs, [ Wfuel[:-1] >= Wfuel[1:] + Wburn[:-1], Wfuel[-1] >= Wburn[-1] ]
def return_radii(nPoints, sol, mrocket): nt = len(sol('A_avg')[0]) nx = len(sol('A_avg')[:, 0]) with Vectorize(nt): with Vectorize(nx): m = Star(nPoints) linkingConstraints = [] for i in m.variables_byname('r_o'): linkingConstraints += [ i <= sol(mrocket.r), m['r_{ii}'] <= m['r_i'], m['r_i'] <= m['r_o'] ] for j in range(nt - 1): linkingConstraints += [ m['r_i'][:, j] <= m['r_i'][:, j + 1], m['r_o'][:, j] <= m['r_o'][:, j + 1], m['r_{ii}'][:, j] <= m['r_{ii}'][:, j + 1], ] cost = np.prod(m['slack']**10) * np.prod( m['r_o'] * m['r_i']**-1 * m['h_e']**-1) m = Model(cost, [m, linkingConstraints], m.substitutions) m.substitutions.update({'A': sol('A_out'), 'C': sol('l_b')}) r_sol = m.localsolve(verbosity=4) return r_sol
def setup(self, aircraft): self.aircraft = aircraft with Vectorize(4): # four flight segments self.fs = FlightSegment(aircraft) Wburn = self.fs.aircraftp.Wburn Wfuel = self.fs.aircraftp.Wfuel self.takeoff_fuel = Wfuel[0] return { "definition of Wburn": Wfuel[:-1] >= Wfuel[1:] + Wburn[:-1], "require fuel for the last leg": Wfuel[-1] >= Wburn[-1], "flight segment": self.fs }
def setup(self, N, aircraft, alt=15000, wind=False, etap=0.7, dh=15000): fs = FlightSegment(N, aircraft, alt, wind, etap) with Vectorize(N): hdot = Variable("\\dot{h}", "ft/min", "Climb rate") deltah = Variable("\\Delta h", dh, "ft", "altitude difference") hdotmin = Variable("\\dot{h}_{min}", 100, "ft/min", "minimum climb rate") constraints = [ hdot*fs.be["t"] >= deltah/N, hdot >= hdotmin, fs.slf["T"] >= (0.5*fs["\\rho"]*fs["V"]**2*fs["C_D"] * fs.aircraft.wing["S"] + fs["W_{start}"]*hdot / fs["V"]), ] return fs, constraints
def setup(self, N, aircraft): self.N = N with Vectorize(self.N): self.drag = AircraftDrag(aircraft, self) Wtotal = self.Wtotal = aircraft.Wtotal CD = self.CD = self.drag.CD CL = self.CL = self.drag.CL S = self.S = aircraft.wing.planform.S E = aircraft.battery.E Poper = self.drag.Poper T = self.drag.T self.rho = rho constraints = [ Wtotal <= 0.5 * rho * V**2 * CL * S, T >= 0.5 * rho * V**2 * CD * S + Wtotal * hdot / V, hdot >= dh / dt, t >= sum(hstack(dt)), E >= sum(hstack(Poper * dt)) ] return self.drag, constraints
def setup(self, N, aircraft, alt=15000, wind=False, etap=0.7): self.aircraft = aircraft with Vectorize(N): self.fs = FlightState(alt, wind) self.aircraftPerf = self.aircraft.flight_model(self.fs) self.slf = SteadyLevelFlight(self.fs, self.aircraft, self.aircraftPerf, etap) self.be = BreguetEndurance(self.aircraftPerf) self.submodels = [self.fs, self.aircraftPerf, self.slf, self.be] Wfuelfs = Variable("W_{fuel-fs}", "lbf", "flight segment fuel weight") self.constraints = [Wfuelfs >= self.be["W_{fuel}"].sum()] if N > 1: self.constraints.extend([self.aircraftPerf["W_{end}"][:-1] >= self.aircraftPerf["W_{start}"][1:]]) return self.aircraft, self.submodels, self.constraints
def setup(self,aircraft,Nmissions,Nsegments): self.aircraft = aircraft self.missions = [] for i in range(0,Nmissions): self.missions.append(Mission(self.aircraft,Nsegments)) # Multimission objective variables W_f_mm = Variable('W_{f_{mm}}','N','multimission fuel weight') with Vectorize(Nmissions): # Mission variables hcruise = Variable('h_{cruise_{mm}}', 'm', 'minimum cruise altitude') Range = Variable("Range_{mm}", "km", "aircraft range") W_p = Variable("W_{p_{mm}}", "N", "payload weight", pr=20.) V_min = Variable("V_{min_{mm}}", 25, "m/s", "takeoff speed", pr=20.) cost_index = Variable("C_{mm}", '1/hr','hourly cost index') TOfac = Variable('T/O factor_{mm}', 2.,'-','takeoff thrust factor') constraints = [] # Setting up the missions for i in range(0,Nmissions): constraints += [ self.missions[i]['h_{cruise_m}'] == hcruise[i], self.missions[i]['Range_m'] == Range[i], self.missions[i]['W_{p_m}'] == W_p[i], self.missions[i]['V_{min_m}'] == V_min[i], self.missions[i]['C_m'] == cost_index[i], self.missions[i]['T/O factor_m'] == TOfac[i], # Upper bounding relevant variables W_f_mm <= 1e11*units('N'), ] # Multimission constraints constraints += [W_f_mm >= sum(self.missions[i]['W_{f_m}'] for i in range(0,Nmissions))] return constraints, self.aircraft, self.missions
def test_init(self): """Test VectorVariable initialization""" # test 1 n = 3 v = VectorVariable(n, 'v', label='dummy variable') self.assertTrue(isinstance(v, NomialArray)) v_mult = 3*v for i in range(n): self.assertTrue(isinstance(v[i], PlainVariable)) self.assertTrue(isinstance(v[i], Monomial)) # test that operations on Variable cast to Monomial self.assertTrue(isinstance(v_mult[i], Monomial)) self.assertFalse(isinstance(v_mult[i], PlainVariable)) # test 2 x = VectorVariable(3, 'x', label='dummy variable') x_0 = Variable('x', idx=(0,), shape=(3,), label='dummy variable') x_1 = Variable('x', idx=(1,), shape=(3,), label='dummy variable') x_2 = Variable('x', idx=(2,), shape=(3,), label='dummy variable') x2 = NomialArray([x_0, x_1, x_2]) self.assertEqual(x, x2) # test inspired by issue 137 N = 20 x_arr = np.arange(0, 5, 5/N) + 1e-6 x = VectorVariable(N, 'x', x_arr, 'm', "Beam Location") with self.assertRaises(ValueError): _ = VectorVariable(2, "x", [1, 2, 3]) with Vectorize(2): x = VectorVariable(3, "x", np.array([13, 15, 17])) self.assertEqual(x[0, 0].value, 13) self.assertEqual(x[1, 0].value, 15) self.assertEqual(x[2, 0].value, 17) self.assertEqual(x[0, 0].value, x[0, 1].value) self.assertEqual(x[1, 0].value, x[1, 1].value) self.assertEqual(x[2, 0].value, x[2, 1].value)
def setup(self, b, cave, tau, N=5): self.N = N rho_cfrp = Variable("\\rho_{CFRP}", 1.6, "g/cm^3", "density of CFRP") E = Variable("E", 2e7, "psi", "Youngs modulus of CF") with Vectorize(self.N - 1): d = Variable("d", "in", "spar diameter") I = Variable("I", "m^4", "spar x moment of inertia") Sy = Variable("S_y", "m**3", "section modulous") A = Variable("A", "in**2", "spar cross sectional area") dm = Variable("dm", "kg", "segment spar mass") W = Variable("W", "lbf", "tube spar weight") g = Variable("g", 9.81, "m/s**2", "gravitational constant") constraints = [ dm >= rho_cfrp * A * b / (N - 1), W >= 2 * dm.sum() * g, cave * tau >= d, 4 * I**2 / A**2 / (d / 2)**2 + A / pi <= (d / 2)**2, Sy * (d / 2) <= I, E == E ] return constraints
def setup(self, static, state, onDesign=False): fd = dirname(abspath(__file__)) + sep + "dai1336a.csv" self.wing = static.wing.flight_model(static.wing, state, fitdata=fd) self.htail = static.emp.htail.flight_model(static.emp.htail, state) self.vtail = static.emp.vtail.flight_model(static.emp.vtail, state) self.tailboom = static.emp.tailboom.flight_model( static.emp.tailboom, state) self.motor = static.motor.flight_model(static.motor, state) if static.sp: if onDesign: static.propeller.flight_model = BladeElementProp self.propeller = static.propeller.flight_model(static.propeller, state) self.flight_models = [ self.wing, self.htail, self.vtail, self.tailboom, self.motor, self.propeller ] e = self.e = self.wing.e cdht = self.cdht = self.htail.Cd cdvt = self.cdvt = self.vtail.Cd Sh = self.Sh = static.Sh Sv = self.Sv = static.Sv Sw = self.Sw = static.Sw cftb = self.cftb = self.tailboom.Cf Stb = self.Stb = static.emp.tailboom.S cdw = self.cdw = self.wing.Cd self.CL = self.wing.CL Nprop = static.Nprop Tprop = self.propeller.T Qprop = self.propeller.Q RPMprop = self.propeller.omega Qmotor = self.motor.Q RPMmotor = self.motor.omega Pelec = self.motor.Pelec self.wing.substitutions[e] = 0.95 self.wing.substitutions[self.wing.CLstall] = 4 self.wing.substitutions[e] = 0.95 dvars = [cdht * Sh / Sw, cdvt * Sv / Sw, cftb * Stb / Sw] if static.Npod is not 0: with Vectorize(static.Npod): self.fuse = static.fuselage.flight_model( static.fuselage, state) self.flight_models.extend([self.fuse]) cdfuse = self.fuse.Cd Sfuse = static.fuselage.S dvars.extend(cdfuse * Sfuse / Sw) self.fuse.substitutions[self.fuse.mfac] = 1.1 constraints = [ cda >= sum(dvars), Tprop == T / Nprop, Qmotor == Qprop, RPMmotor == RPMprop, CD / mfac >= cda + cdw, Poper / mpower >= Pavn + Ppay + (Pelec * Nprop), ] return self.flight_models, constraints
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, 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
def setup(self, Ncoldpipes, Nhotpipes): self.Ncoldpipes = Ncoldpipes self.Nhotpipes = Nhotpipes exec parse_variables(Layer.__doc__) self.material = self.material_model() with Vectorize(Nhotpipes): with Vectorize(Ncoldpipes): cells = self.cells = HXArea(n_fins, self.material) coldfluid = self.coldfluid_model() with Vectorize(Ncoldpipes): coldpipes = RectangularPipe(Nhotpipes, n_fins, coldfluid, increasingT=True) self.coldpipes = coldpipes hotfluid = self.hotfluid_model() with Vectorize(Nhotpipes): hotpipes = RectangularPipe(Ncoldpipes, n_fins, hotfluid, increasingT=False) self.hotpipes = hotpipes pipes = [ coldpipes, coldpipes.T_in == T_in_cold, coldpipes.v_in == v_in_cold, hotpipes, hotpipes.T_in == T_in_hot, hotpipes.v_in == v_in_hot ] self.design_parameters = OrderedDict([ # TODO: add T_max_hot, T_min_cold? ("gravity", g), ("x_width", x_dim), ("y_width", y_dim), ("z_width", z_dim), ("Hot_Channels", self.Nhotpipes), ("Cold_Channels", self.Ncoldpipes), ("Hot_Drag", D_hot), ("Cold_Drag", D_cold), ("c_metal", self.material.c), ("k_metal", self.material.k), ("rho_metal", self.material.rho), ("t_min_metal", self.material.t_min), ("c_coldfluid", coldfluid.c), ("k_coldfluid", coldfluid.k), ("rho_coldfluid", coldfluid.rho), ("mu_coldfluid", coldfluid.mu), ("Ti_coldfluid", T_in_cold), ("vi_coldfluid", v_in_cold), ("c_hotfluid", hotfluid.c), ("k_hotfluid", hotfluid.k), ("rho_hotfluid", hotfluid.rho), ("mu_hotfluid", hotfluid.mu), ("Ti_hotfluid", T_in_hot), ("vi_hotfluid", v_in_hot), ("max_solidity", max_solidity) ]) geom = [ V_tot >= hotpipes.V_seg.sum() + coldpipes.V_seg.sum() + V_mtrl, cells.x_cell == coldpipes.l_seg.T, cells.y_cell == hotpipes.l_seg, maxAR >= cells.y_cell / cells.x_cell, maxAR >= cells.x_cell / cells.y_cell, # Differentiating between flow width and cell width cells.x_cell >= n_fins * (cells.t_hot + hotpipes.w_fluid), cells.y_cell >= n_fins * (cells.t_cld + coldpipes.w_fluid.T), n_fins >= 1., # Making sure there is at least 1 fin cells.dQ == hotpipes.dQ, cells.dQ == coldpipes.dQ.T, cells.Tr_hot == hotpipes.Tr_int, cells.Tr_cld == coldpipes.Tr_int.T, cells.T_hot == hotpipes.T_avg, cells.T_cld == coldpipes.T_avg.T, cells.h_hot == hotpipes.h, cells.h_cld == coldpipes.h.T, cells.z_hot == hotpipes.h_seg, cells.z_cld == coldpipes.h_seg.T, x_dim >= hotpipes.w.sum(), y_dim >= coldpipes.w.sum(), z_dim >= cells.z_hot + cells.z_cld + cells.t_plate, T_max_hot >= cells.T_hot[-1, :], T_min_cold <= cells.T_cld[:, -1], T_min_cold <= T_max_hot ] for j in range(Nhotpipes): for i in range(Ncoldpipes): geom.extend([ cells.x_cell[i, j] == hotpipes.w[j], cells.y_cell[i, j] == coldpipes.w[i], ]) with SignomialsEnabled(): SP_Qsum = Q <= cells.dQ.sum() return [ SP_Qsum, cells, pipes, geom, self.material, # SOLIDITY solidity == V_mtrl / V_tot, solidity <= max_solidity, # DRAG D_hot >= self.hotpipes.D.sum(), D_cold >= self.coldpipes.D.sum(), # TOTAL VOLUME REQUIREMENT V_tot <= x_dim * y_dim * z_dim, # MATERIAL VOLUME V_mtrl >= ((n_fins * cells.z_hot * cells.t_hot * cells.x_cell).sum() + (n_fins * cells.z_cld * cells.t_cld * cells.y_cell).sum() + (cells.x_cell * cells.y_cell * cells.t_plate).sum()), ]
"Example Vectorize usage, from gpkit/tests/t_vars.py" from gpkit import Variable, Vectorize, VectorVariable with Vectorize(3): with Vectorize(5): y = Variable("y") x = VectorVariable(2, "x") z = VectorVariable(7, "z") assert (y.shape == (5, 3)) assert (x.shape == (2, 5, 3)) assert (z.shape == (7, 3))
def setup(self, aircraft, V_cruise=150 * ureg.mph, N_crew=3, N_passengers=1, reserve_type="FAA_heli", mission_type="piloted", loiter_type="level_flight", tailRotor_power_fraction_hover=0.0001, tailRotor_power_fraction_levelFlight=0.0001): if not (aircraft.autonomousEnabled) and (mission_type != "piloted"): raise ValueError("Autonomy is not enabled for Aircraft() model.") W = Variable("W_{mission}", "lbf", "Weight of the aircraft during the mission") C_eff = aircraft.battery.topvar("C_{eff}") #effective battery capacity E_mission = Variable("E_{mission}", "kWh", "Electrical energy used during mission") self.W = W self.E_mission = E_mission self.mission_type = mission_type self.crew = Crew(mission_type=mission_type, N_crew=N_crew, W_oneCrew=225 * ureg.lbf) self.passengers = Passengers(N_passengers=N_passengers, W_onePassenger=225 * ureg.lbf) self.medical_equipment = MedicalEquipment() hoverState = FlightState(h=0 * ureg.ft) constraints = [] self.fs0 = Hover( self, aircraft, hoverState, tailRotor_power_fraction=tailRotor_power_fraction_hover ) #takeoff from base self.fs1 = LevelFlight( self, aircraft, V=V_cruise, tailRotor_power_fraction=tailRotor_power_fraction_levelFlight ) #fly to patient location self.fs2 = Hover( self, aircraft, hoverState, tailRotor_power_fraction=tailRotor_power_fraction_hover ) #Hover/land at patient location self.fs3 = Hover( self, aircraft, hoverState, tailRotor_power_fraction=tailRotor_power_fraction_hover ) #Takeoff from patient location self.fs4 = LevelFlight( self, aircraft, V=V_cruise, tailRotor_power_fraction=tailRotor_power_fraction_levelFlight ) #Fly to hospital self.fs5 = Hover( self, aircraft, hoverState, tailRotor_power_fraction=tailRotor_power_fraction_hover ) #Hover/land at hospital self.fs6 = Hover( self, aircraft, hoverState, tailRotor_power_fraction=tailRotor_power_fraction_hover ) #Takeoff from hospital self.fs7 = LevelFlight( self, aircraft, V=V_cruise, tailRotor_power_fraction=tailRotor_power_fraction_levelFlight ) #Fly to base #Reserve segment if reserve_type == "FAA_aircraft" or reserve_type == "FAA_heli": V_reserve = ((1 / 3.)**( 1 / 4.)) * V_cruise #Approximation for max-endurance speed if reserve_type == "FAA_aircraft": #30-minute loiter time, as per VFR rules for aircraft (daytime only) t_loiter = Variable("t_{loiter}", 30, "minutes", "Loiter time") elif reserve_type == "FAA_heli": #20-minute loiter time, as per VFR rules for helicopters t_loiter = Variable("t_{loiter}", 20, "minutes", "Loiter time") if loiter_type == "level_flight": #loiter segment is a level-flight segment self.fs8 = LevelFlight(self, aircraft, V=V_reserve, segment_type="loiter", tailRotor_power_fraction= tailRotor_power_fraction_levelFlight) elif loiter_type == "hover": #loiter segment is a hover segment self.fs8 = Hover( self, aircraft, hoverState, tailRotor_power_fraction=tailRotor_power_fraction_hover) constraints += [t_loiter == self.fs8.topvar("t")] if reserve_type == "Uber": #2-nautical-mile diversion distance; used by McDonald & German V_reserve = V_cruise R_divert = Variable("R_{divert}", 2, "nautical_mile", "Diversion distance") self.fs8 = LevelFlight( self, aircraft, V=V_reserve, segment_type="cruise", tailRotor_power_fraction=tailRotor_power_fraction_levelFlight ) #reserve segment constraints += [R_divert == self.fs8.topvar("segment_range")] self.fs9 = Hover( self, aircraft, hoverState, tailRotor_power_fraction=tailRotor_power_fraction_hover ) #Land at base self.time_on_ground = TimeOnGround(self) #Charging self.flight_segments = [self.fs0, self.fs1, self.fs2, self.fs3, self.fs4,\ self.fs5, self.fs6, self.fs7, self.fs8, self.fs9]#all segments included self.cruise_segments = [self.fs1, self.fs4, self.fs7] #loiter not included self.hover_segments = [self.fs0, self.fs2, self.fs3, self.fs5, self.fs6,\ self.fs9] #Power and energy consumption by mission segment with Vectorize(len(self.flight_segments)): P_battery = Variable("P_{battery}", "kW", "Segment power draw") E = Variable("E", "kWh", "Segment energy use") #Segment range constraints with Vectorize(len(self.cruise_segments)): segment_range = Variable("segment_range", "nautical_mile", "Segment range") #Data from hover segments with Vectorize(len(self.hover_segments)): t_hover = Variable("t_{hover}", "s", "Segment hover time") CT = Variable("CT", "-", "Thrust coefficient") CP = Variable("CP", "-", "Power coefficient") Q_perRotor = Variable("Q_perRotor", "lbf*ft", "Torque per lifting rotor") T_perRotor = Variable("T_perRotor", "lbf", "Thrust per lifting rotor") P = Variable("P", "kW", "Total power supplied to all lifting rotors") P_perRotor = Variable("P_perRotor", "kW", "Power per lifting rotor") VT = Variable("VT", "ft/s", "Propeller tip speed") omega = Variable("\omega", "rpm", "Propeller angular velocity") MT = Variable("MT", "-", "Propeller tip Mach number") FOM = Variable("FOM", "-", "Figure of merit") p_ratio = Variable("p_{ratio}", "-", "Sound pressure ratio in hover") constraints += [self.flight_segments, self.time_on_ground] constraints += [self.crew, self.passengers] constraints += [W >= aircraft.topvar("W_{empty}") + self.passengers.topvar("W") \ + self.crew.topvar("W") + self.medical_equipment.topvar("W")] constraints += [aircraft.topvar("MTOW") >= W] #Mission-segment constraints constraints += [ segment_range[i] == segment.topvar("segment_range") for i, segment in enumerate(self.cruise_segments) ] constraints += [ t_hover[i] == segment.topvar("t") for i, segment in enumerate(self.hover_segments) ] constraints += [hoverState] constraints += [ E_mission >= sum(c.topvar("E") for c in self.flight_segments) ] constraints += [C_eff >= E_mission] constraints += [ P_battery[i] == segment.topvar("P_{battery}") for i, segment in enumerate(self.flight_segments) ] constraints += [ E[i] == segment.topvar("E") for i, segment in enumerate(self.flight_segments) ] constraints += [ CT[i] == segment.rotorPerf.topvar("CT") for i, segment in enumerate(self.hover_segments) ] constraints += [ CP[i] == segment.rotorPerf.topvar("CP") for i, segment in enumerate(self.hover_segments) ] constraints += [ Q_perRotor[i] == segment.rotorPerf.topvar("Q_perRotor") for i, segment in enumerate(self.hover_segments) ] constraints += [ T_perRotor[i] == segment.rotorPerf.topvar("T_perRotor") for i, segment in enumerate(self.hover_segments) ] constraints += [ P[i] == segment.rotorPerf.topvar("P") for i, segment in enumerate(self.hover_segments) ] constraints += [ P_perRotor[i] == segment.rotorPerf.topvar("P_perRotor") for i, segment in enumerate(self.hover_segments) ] constraints += [ VT[i] == segment.rotorPerf.topvar("VT") for i, segment in enumerate(self.hover_segments) ] constraints += [ omega[i] == segment.rotorPerf.topvar("\omega") for i, segment in enumerate(self.hover_segments) ] constraints += [ MT[i] == segment.rotorPerf.topvar("MT") for i, segment in enumerate(self.hover_segments) ] constraints += [ FOM[i] == segment.rotorPerf.topvar("FOM") for i, segment in enumerate(self.hover_segments) ] constraints += [ p_ratio[i] == segment.rotorPerf.topvar("p_{ratio}") for i, segment in enumerate(self.hover_segments) ] #Mission time t_flight = Variable("t_{flight}", "s", "Time in flight") t_mission = Variable("t_{mission}", "s", "Mission time (including charging)") constraints += [ t_flight >= sum(c.topvar("t") for c in self.flight_segments) ] constraints += [ t_mission >= t_flight + self.time_on_ground.topvar("t") ] return constraints
def setup(self, Nclimb1, Nclimb2, Ncruise, substitutions = None, **kwargs): eng = 0 # vectorize with Vectorize(Nclimb1 +Nclimb2 + Ncruise): enginestate = FlightState() #build the submodel ac = Aircraft(Nclimb1 + Nclimb2, Ncruise, enginestate, eng) #Vectorize with Vectorize(Nclimb1): climb1 = ClimbSegment(ac) #Vectorize with Vectorize(Nclimb2): climb2 = ClimbSegment(ac) with Vectorize(Ncruise): cruise = CruiseClimbSegment(ac) statelinking = StateLinking(climb1.state, climb2.state, cruise.state, enginestate, Nclimb1, Nclimb2, Ncruise) #declare new variables W_ftotal = Variable('W_{f_{total}}', 'N', 'Total Fuel Weight') W_fclimb1 = Variable('W_{f_{climb1}}', 'N', 'Fuel Weight Burned in Climb 1') W_fclimb2 = Variable('W_{f_{climb2}}', 'N', 'Fuel Weight Burned in Climb 2') W_fcruise = Variable('W_{f_{cruise}}', 'N', 'Fuel Weight Burned in Cruise') W_total = Variable('W_{total}', 'N', 'Total Aircraft Weight') CruiseAlt = Variable('CruiseAlt', 'ft', 'Cruise Altitude [feet]') ReqRng = Variable('ReqRng', 'nautical_miles', 'Required Cruise Range') W_dry = Variable('W_{dry}', 'N', 'Aircraft Dry Weight') RCmin = Variable('RC_{min}', 'ft/min', 'Minimum allowed climb rate') dhftholdcl1 = Variable('dhftholdcl1', 'ft', 'Climb 1 Hold Variable') dhftholdcl2 = Variable('dhftholdcl2', 'ft', 'Climb 2 Hold Variable') dhftholdcr = Variable('dhftholdcr', 'ft', 'Cruise Hold Variable') h1 = climb1['h'] hftClimb1 = climb1['hft'] dhftcl1 = climb1['dhft'] h2 = climb2['h'] hftClimb2 = climb2['hft'] dhftcl2 = climb2['dhft'] dhftcr = cruise['dhft'] hftCruise = cruise['hft'] #make overall constraints constraints = [] with SignomialsEnabled(): constraints.extend([ #weight constraints TCS([ac['W_{e}'] + ac['W_{payload}'] + ac['numeng'] * ac['W_{engine}'] + ac['W_{wing}'] <= W_dry]), TCS([W_dry + W_ftotal <= W_total]), climb1['W_{start}'][0] == W_total, climb1['W_{end}'][-1] == climb2['W_{start}'][0], climb2['W_{end}'][-1] == cruise['W_{start}'][0], TCS([climb1['W_{start}'] >= climb1['W_{end}'] + climb1['W_{burn}']]), TCS([climb2['W_{start}'] >= climb2['W_{end}'] + climb2['W_{burn}']]), TCS([cruise['W_{start}'] >= cruise['W_{end}'] + cruise['W_{burn}']]), climb1['W_{start}'][1:] == climb1['W_{end}'][:-1], climb2['W_{start}'][1:] == climb2['W_{end}'][:-1], cruise['W_{start}'][1:] == cruise['W_{end}'][:-1], TCS([W_dry <= cruise['W_{end}'][-1]]), TCS([W_ftotal >= W_fclimb1 + W_fclimb2 + W_fcruise]), TCS([W_fclimb1 >= sum(climb1['W_{burn}'])]), TCS([W_fclimb2 >= sum(climb2['W_{burn}'])]), TCS([W_fcruise >= sum(cruise['W_{burn}'])]), #altitude constraints hftCruise[0] == CruiseAlt, ## TCS([hftCruise[1:Ncruise] >= hftCruise[:Ncruise-1] + dhftcr]), SignomialEquality(hftCruise[1:Ncruise], hftCruise[:Ncruise-1] + dhftholdcr), TCS([hftClimb2[1:Nclimb2] <= hftClimb2[:Nclimb2-1] + dhftholdcl2]), TCS([hftClimb2[0] <= dhftholdcl2 + 10000*units('ft')]), hftClimb2[-1] == hftCruise, TCS([hftClimb1[1:Nclimb1] >= hftClimb1[:Nclimb1-1] + dhftholdcl1]), TCS([hftClimb1[0] == dhftcl1[0]]), hftClimb1[-1] == 10000*units('ft'), #compute the dh2 dhftholdcl2 >= (hftCruise-10000*units('ft'))/Nclimb2, ## SignomialEquality(dhftholdcl2, (hftCruise-10000*units('ft'))/Nclimb2,), dhftholdcl2 == dhftcl2, #compute the dh1 dhftholdcl1 == 10000*units('ft')/Nclimb1, dhftholdcl1 == dhftcl1, dhftcr == dhftholdcr, sum(cruise['RngCruise']) + sum(climb2['RngClimb']) + sum(climb1['RngClimb']) >= ReqRng, #compute fuel burn from TSFC cruise['W_{burn}'] == ac['numeng']*ac.engine['TSFC'][Nclimb1 + Nclimb2:] * cruise['thr'] * ac.engine['F'][Nclimb1 + Nclimb2:], climb1['W_{burn}'] == ac['numeng']*ac.engine['TSFC'][:Nclimb1] * climb1['thr'] * ac.engine['F'][:Nclimb1], climb2['W_{burn}'] == ac['numeng']*ac.engine['TSFC'][Nclimb1:Nclimb1 + Nclimb2] * climb2['thr'] * ac.engine['F'][Nclimb1:Nclimb1 + Nclimb2], #min climb rate constraint ## climb1['RC'][0] >= RCmin, climb1['V'] <= 250*units('knots'), ]) M2 = .8 M25 = .6 M4a = .1025 Mexit = 1 M0 = .8 engineclimb1 = [ ac.engine.engineP['M_2'][:Nclimb1] == climb1['M'], ac.engine.engineP['M_{2.5}'] == M25, ac.engine.engineP['hold_{2}'] == 1+.5*(1.398-1)*M2**2, ac.engine.engineP['hold_{2.5}'] == 1+.5*(1.354-1)*M25**2, ac.engine.engineP['c1'] == 1+.5*(.401)*M0**2, #constraint on drag and thrust ac['numeng']*ac.engine['F_{spec}'][:Nclimb1] >= climb1['D'] + climb1['W_{avg}'] * climb1['\\theta'], #climb rate constraints TCS([climb1['excessP'] + climb1.state['V'] * climb1['D'] <= climb1.state['V'] * ac['numeng'] * ac.engine['F_{spec}'][:Nclimb1]]), ] M2 = .8 M25 = .6 M4a = .1025 Mexit = 1 M0 = .8 engineclimb2 = [ ac.engine.engineP['M_2'][Nclimb1:Nclimb1 + Nclimb2] == climb2['M'], #constraint on drag and thrust ac['numeng']*ac.engine['F_{spec}'][Nclimb1:Nclimb1 + Nclimb2] >= climb2['D'] + climb2['W_{avg}'] * climb2['\\theta'], #climb rate constraints TCS([climb2['excessP'] + climb2.state['V'] * climb2['D'] <= climb2.state['V'] * ac['numeng'] * ac.engine['F_{spec}'][Nclimb1:Nclimb1 + Nclimb2]]), ] M2 = .8 M25 = .6 M4a = .1025 Mexit = 1 M0 = .8 enginecruise = [ ac.engine.engineP['M_2'][Nclimb1 + Nclimb2:] == cruise['M'], ## cruise['M'] >= .7, #constraint on drag and thrust ac['numeng'] * ac.engine['F_{spec}'][Nclimb1 + Nclimb2:] >= cruise['D'] + cruise['W_{avg}'] * cruise['\\theta'], #climb rate constraints TCS([cruise['excessP'] + cruise.state['V'] * cruise['D'] <= cruise.state['V'] * ac['numeng'] * ac.engine['F_{spec}'][Nclimb1 + Nclimb2:]]), ] return constraints + ac + climb1 + climb2 + cruise + enginecruise + engineclimb1 + engineclimb2 + enginestate + statelinking
def setup(self, 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
"Vectorization demonstration" from gpkit import Model, Variable, Vectorize class Test(Model): """A simple scalar model Upper Unbounded --------------- x """ def setup(self): x = self.x = Variable("x") return [x >= 1] print "SCALAR" m = Test() m.cost = m["x"] print m.solve(verbosity=0).summary() print "__________\n" print "VECTORIZED" with Vectorize(3): m = Test() m.cost = m["x"].prod() m.append(m["x"][1] >= 2) print m.solve(verbosity=0).summary()
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, 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
def setup(self, Npod=0, sp=False): self.Npod = Npod self.sp = sp cfrpud.substitutions.update({ cfrpud.rho: 1.5, cfrpud.E: 200, cfrpud.tmin: 0.1, cfrpud.sigma: 1500 }) cfrpfabric.substitutions.update({ cfrpfabric.rho: 1.3, cfrpfabric.E: 40, cfrpfabric.tmin: 0.1, cfrpfabric.sigma: 300, cfrpfabric.tau: 80 }) foamhd.substitutions.update({foamhd.rho: 0.03}) materials = [cfrpud, cfrpfabric, foamhd] HorizontalTail.sparModel = BoxSparGP HorizontalTail.fillModel = None HorizontalTail.skinModel = WingSecondStruct VerticalTail.sparModel = BoxSparGP VerticalTail.fillModel = None VerticalTail.skinModel = WingSecondStruct TailBoom.__bases__ = (BoxSparGP, ) TailBoom.secondaryWeight = True self.emp = Empennage(N=5) self.solarcells = SolarCells() self.battery = Battery() if sp: WingSP.sparModel = BoxSparSP WingSP.fillModel = None WingSP.skinModel = WingSecondStruct self.wing = WingSP(N=20) else: WingGP.sparModel = BoxSparGP WingGP.fillModel = None WingGP.skinModel = WingSecondStruct self.wing = WingGP(N=20) self.motor = Motor() Propeller.flight_model = ActuatorProp self.propeller = Propeller() self.components = [self.solarcells, self.wing, self.battery, self.emp] self.propulsor = [self.motor, self.propeller] Sw = self.Sw = self.wing.planform.S cmac = self.cmac = self.wing.planform.cmac tau = self.tau = self.wing.planform.tau croot = self.croot = self.wing.planform.croot b = self.b = self.wing.planform.b Vh = self.Vh = self.emp.htail.Vh lh = self.lh = self.emp.htail.lh Sh = self.Sh = self.emp.htail.planform.S Vv = self.Vv = self.emp.vtail.Vv Sv = self.Sv = self.emp.vtail.planform.S lv = self.lv = self.emp.vtail.lv d0 = self.d0 = self.emp.tailboom.d0 Ssolar = self.Ssolar = self.solarcells.S mfsolar = self.mfsolar = self.solarcells.mfac Volbatt = self.battery.Volbatt vttau = self.emp.vtail.planform.tau httau = self.emp.htail.planform.tau self.emp.substitutions[Vv] = 0.02 self.emp.substitutions[self.emp.htail.skin.rhoA] = 0.4 self.emp.substitutions[self.emp.vtail.skin.rhoA] = 0.4 self.emp.substitutions[self.emp.tailboom.wlim] = 1.0 self.wing.substitutions[self.wing.mfac] = 1.0 if not sp: self.emp.substitutions[Vh] = 0.45 self.emp.substitutions[self.emp.htail.mh] = 0.1 constraints = [ Ssolar * mfsolar <= Sw, Vh <= Sh * lh / Sw / cmac, Vv <= Sv * lv / Sw / b, d0 <= tau * croot, Wland >= fland * Wtotal, vttau >= minvttau, httau >= minhttau, tau <= maxtau ] if self.Npod is not 0: with Vectorize(1): with Vectorize(self.Npod): self.fuselage = Fuselage() self.k = self.fuselage.k Volfuse = self.Volfuse = self.fuselage.Vol[:, 0] Wbatt = self.battery.W Wfuse = sum(self.fuselage.W) self.fuselage.substitutions[self.fuselage.nply] = 5 constraints.extend([ Volbatt <= Volfuse, Wwing >= self.wing.W + self.solarcells.W, Wcent >= (Wpay + Wavn + self.emp.W + self.motor.W * Nprop + self.fuselage.W[0] + Wbatt / self.Npod), Wtotal / mfac >= (Wpay + Wavn + Wland + Wfuse + sum([c.W for c in self.components]) + (Nprop) * sum([c.W for c in self.propulsor])) ]) self.components.append(self.fuselage) else: constraints.extend([ Wwing >= sum( [c.W for c in [self.wing, self.battery, self.solarcells]]), Wcent >= Wpay + Wavn + self.emp.W + self.motor.W * Nprop, Volbatt <= cmac**2 * 0.5 * tau * b, Wtotal / mfac >= (Wpay + Wavn + Wland + sum([c.W for c in self.components]) + Nprop * sum([c.W for c in self.propulsor])) ]) return constraints, self.components, materials, self.propulsor