def __init__(self, N=4, **kwargs): EI = Variable("EI", 1e4, "N*m^2") dx = Variable("dx", "m", "Length of an element") L = Variable("L", 5, "m", "Overall beam length") q = VectorVariable(N, "q", 100*np.ones(N), "N/m", "Distributed load at each point") V = VectorVariable(N, "V", "N", "Internal shear") V_tip = Variable("V_{tip}", 0, "N", "Tip loading") M = VectorVariable(N, "M", "N*m", "Internal moment") M_tip = Variable("M_{tip}", 0, "N*m", "Tip moment") th = VectorVariable(N, "\\theta", "-", "Slope") th_base = Variable("\\theta_{base}", 0, "-", "Base angle") w = VectorVariable(N, "w", "m", "Displacement") w_base = Variable("w_{base}", 0, "m", "Base deflection") # below: trapezoidal integration to form a piecewise-linear # approximation of loading, shear, and so on # shear and moment increase from tip to base (left > right) shear_eq = (V >= V.right + 0.5*dx*(q + q.right)) shear_eq[-1] = (V[-1] >= V_tip) # tip boundary condition moment_eq = (M >= M.right + 0.5*dx*(V + V.right)) moment_eq[-1] = (M[-1] >= M_tip) # slope and displacement increase from base to tip (right > left) theta_eq = (th >= th.left + 0.5*dx*(M + M.left)/EI) theta_eq[0] = (th[0] >= th_base) # base boundary condition displ_eq = (w >= w.left + 0.5*dx*(th + th.left)) displ_eq[0] = (w[0] >= w_base) # minimize tip displacement (the last w) Model.__init__(self, w[-1], [shear_eq, moment_eq, theta_eq, displ_eq, L == (N-1)*dx], **kwargs)
def __init__(self, N=4, **kwargs): EI = Variable("EI", 1e4, "N*m^2") dx = Variable("dx", "m", "Length of an element") L = Variable("L", 5, "m", "Overall beam length") q = VectorVariable(N, "q", 100 * np.ones(N), "N/m", "Distributed load at each point") V = VectorVariable(N, "V", "N", "Internal shear") V_tip = Variable("V_{tip}", 0, "N", "Tip loading") M = VectorVariable(N, "M", "N*m", "Internal moment") M_tip = Variable("M_{tip}", 0, "N*m", "Tip moment") th = VectorVariable(N, "\\theta", "-", "Slope") th_base = Variable("\\theta_{base}", 0, "-", "Base angle") w = VectorVariable(N, "w", "m", "Displacement") w_base = Variable("w_{base}", 0, "m", "Base deflection") # below: trapezoidal integration to form a piecewise-linear # approximation of loading, shear, and so on # shear and moment increase from tip to base (left > right) shear_eq = (V >= V.right + 0.5 * dx * (q + q.right)) shear_eq[-1] = (V[-1] >= V_tip) # tip boundary condition moment_eq = (M >= M.right + 0.5 * dx * (V + V.right)) moment_eq[-1] = (M[-1] >= M_tip) # slope and displacement increase from base to tip (right > left) theta_eq = (th >= th.left + 0.5 * dx * (M + M.left) / EI) theta_eq[0] = (th[0] >= th_base) # base boundary condition displ_eq = (w >= w.left + 0.5 * dx * (th + th.left)) displ_eq[0] = (w[0] >= w_base) # minimize tip displacement (the last w) Model.__init__( self, w[-1], [shear_eq, moment_eq, theta_eq, displ_eq, L == (N - 1) * dx], **kwargs)
def __init__(self, min_rho=True, **kwargs): self.min_rho = min_rho Lval = 0.0065 # [K/m] th = GRAVITATIONAL_ACCEL/(GAS_CONSTANT*Lval) # [-] L = Variable('L', Lval, 'K/m', 'Temperature lapse rate') p_0 = Variable('p_0', 101325, 'Pa', 'Pressure at sea level') T_0 = Variable('T_0', 288.15, 'K', 'Temperature at sea level') if min_rho: objective = rho # minimize density else: objective = 1/rho # maximize density # Temperature lapse rate constraint if min_rho: with SignomialsEnabled(): constraints = TCS([T_0 <= T + L*h]) else: constraints = TCS([T_0 >= T + L*h]) constraints += [h <= 11000*units.m, h >= 1E-6*units.m, # Pressure-altitude relation (p/p_0)**(1/th) == T/T_0, # Ideal gas law rho == p/(R*T), ] su = Sutherland() lc = su.link(constraints) Model.__init__(self, objective, lc, **kwargs)
def __init__(self, **kwargs): T_s = Variable('T_s', 110.4, "K", "Sutherland Temperature") C_1 = Variable('C_1', 1.458E-6, "kg/(m*s*K^0.5)", 'Sutherland coefficient') t_plus_ts_approx = (T + T_s).mono_approximation({T: 288.15, T_s: T_s.value}) objective = mu constraints = [t_plus_ts_approx * mu == C_1 * T**1.5] Model.__init__(self, objective, constraints, **kwargs)
def __init__(self, **kwargs): T_tp = 216.65 k = GRAVITATIONAL_ACCEL/(GAS_CONSTANT*T_tp) p11 = Variable('p_{11}', 22630, 'Pa', 'Pressure at 11 km') objective = 1/rho # maximize density constraints = [h >= 11*units.km, h <= 20*units.km, # Temperature is constant in the tropopause T == T_tp, # Pressure-altitude relation, using taylor series exp TCS([np.exp(k*11000)*p11/p >= 1 + te_exp_minus1(g/(R*T)*h, 15)], reltol=1E-4), # Ideal gas law rho == p/(R*T), ] su = Sutherland() lc = su.link(constraints) Model.__init__(self, objective, lc, **kwargs)
def __init__(self): y = Variable('y') Model.__init__(self, y, [y >= 2])
def __init__(self): x = Variable('x') y = Variable('y') Model.__init__(self, x, Sub().link([x >= y, y >= 1]))
def __init__(self): x = Variable("x", "m") x_min = Variable("x_{min}", 1, "cm") Model.__init__(self, x, [x >= x_min])
def __init__(self): x = Variable("x", "ft") x_max = Variable("x_{max}", 1, "yard") Model.__init__(self, 1 / x, [x <= x_max])
def __init__(self): y = Variable('y') Model.__init__(self, y, [y >= 2])
def __init__(self): x = Variable('x') y = Variable('y') Model.__init__(self, x, Sub().link([x >= y, y >= 1]))
def __init__(self): x = Variable("x", "m") x_min = Variable("x_{min}", 1, "cm") Model.__init__(self, x, [x >= x_min])
def __init__(self): x = Variable("x", "ft") x_max = Variable("x_{max}", 1, "yard") Model.__init__(self, 1/x, [x <= x_max])
def __init__(self, **kwargs): # Variables A = Variable('A', '-', 'Aspect ratio') b = Variable('b', 'm', 'Span') Icap = Variable('I_{cap}', '-', 'Non-dim spar cap area moment of inertia') Mr = Variable('M_r', 'N', 'Root moment per root chord') nu = Variable('\\nu', '-', 'Dummy variable = $(t^2 + t + 1)/(t+1)$') p = Variable('p', '-', 'Substituted variable = 1 + 2*taper') q = Variable('q', '-', 'Substituted variable = 1 + taper') S = Variable('S', 'm^2', 'Reference area') tau = Variable('\\tau', '-', 'Thickness to chord ratio') tcap = Variable('t_{cap}' ,'-', 'Non-dim. spar cap thickness') tweb = Variable('t_{web}', '-', 'Non-dim. shear web thickness') Wcap = Variable('W_{cap}', 'N', 'Weight of spar caps') Wweb = Variable('W_{web}', 'N', 'Weight of shear web') Wstruct = Variable('W_{struct}', 'N', 'Structural weight') # Constants taper = Variable('taper', 0.45, '-', 'Taper ratio') Lmax = Variable('L_{max}', 'N', 'Maximum wing load') fwadd = Variable('f_{w,add}', 0.4, '-', 'Wing added weight fraction') # TASOPT code (737.tas) g = Variable('g', 9.81, 'm/s^2', 'Gravitational acceleration') Nlift = Variable('N_{lift}', 2.0, '-', 'Wing loading multiplier') rh = Variable('r_h', 0.75, '-', 'Fractional wing thickness at spar web') rhocap = Variable('\\rho_{cap}', 2700, 'kg/m^3', 'Density of spar cap material') rhoweb = Variable('\\rho_{web}', 2700, 'kg/m^3', 'Density of shear web material') sigmax = Variable('\\sigma_{max}', 250e6, 'Pa', 'Allowable tensile stress') sigmaxshear = Variable('\\sigma_{max,shear}', 167e6, 'Pa', 'Allowable shear stress') w = Variable('w', 0.5, '-', 'Wingbox-width-to-chord ratio') objective = Wstruct constraints = [ # Aspect ratio definition A == b**2/S, # Defining taper dummy variables p >= 1 + 2*taper, 2*q >= 1 + p, # Upper bound on maximum thickness tau <= 0.15, # Root moment calculation (see Hoburg 2014) # Depends on a given load the wing must support, Lmax # Assumes lift per unit span proportional to local chord Mr >= Lmax*A*p/24, # Root stiffness (see Hoburg 2014) # Assumes rh = 0.75, so that rms box height = ~0.92*tmax 0.92*w*tau*tcap**2 + Icap <= 0.92**2/2*w*tau**2*tcap, # Stress limit # Assumes bending stress carried by caps (Icap >> Iweb) 8 >= Nlift*Mr*A*q**2*tau/(S*Icap*sigmax), # Shear web sizing # Assumes all shear loads are carried by web and rh=0.75 12 >= A*Lmax*Nlift*q**2/(tau*S*tweb*sigmaxshear), # Posynomial approximation of nu=(1+lam+lam^2)/(1+lam^2) nu**3.94 >= 0.86*p**(-2.38)+ 0.14*p**0.56, # Weight of spar caps and shear webs Wcap >= 8*rhocap*g*w*tcap*S**1.5*nu/(3*A**0.5), Wweb >= 8*rhoweb*g*rh*tau*tweb*S**1.5*nu/(3*A**0.5), # Total wing weight using an additional weight fraction Wstruct >= (1 + fwadd)*(Wweb + Wcap), ] Model.__init__(self, objective, constraints, **kwargs)
def __init__(self): CL = Variable('C_L', '-', 'Lift coefficient') CLmax = Variable('C_{L_{max}}', '-', 'Max lift coefficient') CD = Variable('C_D', '-', 'Drag coefficient') D = Variable('D', 'N', 'Total aircraft drag (cruise)') Dfuse = Variable('D_{fuse}', 'N', 'Fuselage drag') Dht = Variable('D_{ht}', 'N', 'Horizontal tail drag') Dvt = Variable('D_{vt}', 'N', 'Vertical tail drag') Dwing = Variable('D_{wing}', 'N', 'Wing drag') LD = Variable('\\frac{L}{D}', '-', 'Lift/drag ratio') Lh = Variable('L_h', 'N', 'Horizontal tail downforce') Lw = Variable('L_w', 'N', 'Wing lift') M = Variable('M', '-', 'Cruise Mach number') R = Variable('Range', 'nautical_miles', 'Range') Sw = Variable('S_w', 'm**2', 'Wing reference area') Te = Variable('T_e', 'N', 'Engine thrust at takeoff') TSFC = Variable('c_T', 'lb/lbf/hr', 'Thrust specific fuel consumption') V = Variable('V_{\\infty}', 'm/s', 'Cruise velocity') VTO = Variable('V_{TO}', 'm/s', 'Takeoff speed') W = Variable('W', 'N', 'Total aircraft weight') Weng = Variable('W_{eng}', 'N', 'Engine weight') Wfuel = Variable('W_{fuel}', 'N', 'Fuel weight') Wfuse = Variable('W_{fuse}', 'N', 'Fuselage weight') Wht = Variable('W_{ht}', 'N', 'Horizontal tail weight') Wlg = Variable('W_{lg}', 'N', 'Landing gear weight') Wpay = Variable('W_{pay}', 'N', 'Payload weight') Wvt = Variable('W_{vt}', 'N', 'Vertical tail weight') Wwing = Variable('W_{wing}', 'N', 'Wing weight') Wzf = Variable('W_{zf}', 'N', 'Zero fuel weight') a = Variable('a', 'm/s', 'Speed of sound (35,000 ft)') g = Variable('g', 9.81, 'm/s^2', 'Gravitational acceleration') lr = Variable('l_r', 5000, 'ft', 'Runway length') rho = Variable('\\rho', 'kg/m^3', 'Air density (cruise)') rho0 = Variable('\\rho_0', 'kg/m^3', 'Air density (sea level)') xCG = Variable('x_{CG}', 'm', 'x-location of CG') xCGeng = Variable('x_{CG_{eng}}', 'm', 'x-location of engine CG') xCGfu = Variable('x_{CG_{fu}}', 'm', 'x-location of fuselage CG') xCGht = Variable('x_{CG_{ht}}', 'm', 'x-location of htail CG') xCGlg = Variable('x_{CG_{lg}}', 'm', 'x-location of landing gear CG') xCGvt = Variable('x_{CG_{vt}}', 'm', 'x-location of vtail CG') xCGwing = Variable('x_{CG_{wing}}', 'm', 'x-location of wing CG') xTO = Variable('x_{TO}', 'm', 'Takeoff distance') xi = Variable('\\xi', '-', 'Takeoff parameter') xw = Variable('x_w', 'm', 'x-location of wing aerodynamic center') y = Variable('y', '-', 'Takeoff parameter') z_bre = Variable('z_{bre}', '-', 'Breguet parameter') with SignomialsEnabled(): objective = Wfuel # High level constraints hlc = [ # Drag and weight buildup D >= Dvt + Dfuse + Dwing + Dht, Wzf >= Wvt + Wfuse + Wlg + Wwing + Wht + Weng + Wpay, W >= Wzf + Wfuel, # Range equation for a jet V == M*a, D == 0.5*rho*V**2*Sw*CD, W == 0.5*rho*V**2*Sw*CL, LD == CL/CD, Lw >= W, # TODO: add Lh R <= z_bre*LD*V/(TSFC*g), Wfuel/Wzf >= te_exp_minus1(z_bre, nterm=3), # CG relationships TCS([xCG*W >= Wvt*xCGvt + Wfuse*xCGfu + Wlg*xCGlg + Wwing*xCGwing + Wht*xCGht + Weng*xCGeng + Wfuel*xCGwing + Wpay*xCGfu], reltol=1E-2, raiseerror=False), xw == xCGwing, xCGeng == xCGwing, #Takeoff relationships xi >= 0.5*rho0*VTO**2*Sw*CD/Te, 4*g*xTO*Te/(W*VTO**2) >= 1 + y, 1 >= 0.0464*xi**2.73/y**2.88 + 1.044*xi**0.296/y**0.049, VTO == 1.2*(2*W/(rho0*Sw*CLmax))**0.5, xTO <= lr, ] # Subsystem models vt = VerticalTail.coupled737() fu = Fuselage.coupled737() lg = LandingGear.coupled737() ht = HorizontalTail.coupled737() wi = Wing.coupled737() wb = WingBox() substitutions = { 'C_{L_{max}}': 2.5, 'M': 0.78, 'Range': 3000, 'c_T': 0.3, 'W_{eng}': 10000, 'a': 297, } lc = LinkedConstraintSet([hlc, vt, fu, lg, ht, wi], exclude=[vk.name for vk in wb.varkeys if not vk.value]) Model.__init__(self, objective, lc, substitutions)