def analyze(astnode, toplevel=False): """ Analyze an AstNode and return a CodeObject. 'The result of calling analyze is the execution procedure to be applied to the environment [...] the procedures to which we dispatch perform only analysis, not full evaluation' [ABELSON et al., 1996] @param AstNode astnode @param bool toplevel @returns CodeObject """ try: exp = astnode.exp # Atomic data types and symbols if self_eval(exp): return CodeObject(astnode, lambda env: exp) elif isa(exp, Symbol): return CodeObject(astnode, lambda env: env.find(exp)[exp]) # Compound expressions elif isa(exp, list): if is_dict_literal(exp): return analyze_dict_literal(astnode) if is_if(exp): return analyze_if(astnode) elif is_begin(exp): return analyze_begin(astnode, toplevel) elif is_assignment(exp): return analyze_assignment(astnode) elif is_let(exp): return analyze_let(astnode) elif is_lambda_shorthand(exp): return analyze_lambda_shorthand(astnode) elif is_vardef(exp): return analyze_vardef(astnode) elif is_procdef(exp): return analyze_procdef(astnode) elif is_macrodef(exp): return analyze_macrodef(astnode, toplevel) elif is_macro_application(exp): return analyze_macro_application(astnode) elif is_quoted(exp): return analyze_quotation(astnode) elif is_builtin_proc_application(exp): return analyze_builtin_proc_application(astnode) elif is_attribute_access(exp): return analyze_attribute_access(astnode) else: # If we haven't been able to determine an expression type so far, # we assume that it is a procedure call. return analyze_procedure_application(astnode) else: raise TypeError("Unknown expression type: %s" % to_string(exp)) except Exception as e: add_exc_info(astnode, e) raise e
def get_dth(): Cd = 0.030 # obtenu par lecture graphique à partir de la courbe polaire séance1 # Cl = 0.3706 : fct get_Cl() # alpha_eq = 3.66° : courbe q5 séance 1 # delat_THR_eq = -8.77° : courbe q4 séance1 f = get_Cl() / Cd F = PLANE.m * PLANE.g / f rho0 = utils.isa(h[1])[1] rho = utils.isa(h[1])[1] dth = F / (PLANE.F0 * (rho / rho0)**(0.6) * (0.568 + 0.25 * (1.2 - Ma[1])**3)) return dth
def is_tagged(exp, tag): """ Returns True if the first node of an <exp> is <tag>. Used in many other expression type predicates. @param str | Symbol tag @returns bool """ if isa(exp, list) and isa(exp[0], AstNode): if isa(tag, Symbol): return exp[0].exp == tag else: return exp[0].exp is Sym(tag)
def pousse_max(h, mach): M = np.linspace(mach[0], mach[1], 100) rho0 = utils.isa(0)[1] F0 = PLANE.F0 plt.figure(0) for h_i in h : F = F0*(utils.isa(h_i)[1]/rho0)**(0.6)*(0.568+0.25*(1.2-M)**3) plt.plot(M, F, label='$h={:.0f}$'.format(h_i)) plt.xlabel("$M_a$") plt.ylabel("$F$") plt.title("Evolution de la poussée maximale avec l'altitude et le nombre de Mach") plt.legend() plt.savefig(file+"q1"+format) plt.show()
def coef_pousseel(X, U, P): ''' :return: retourne coef tel que F = coef * deltath ''' p, rho, T = ut.isa(X[s_h]) rho0 = 1.225 mach = get_mach(X[s_va], T) return P.F0 * math.pow(rho / rho0, 0.6) * (0.568 + 0.25 * math.pow(1.2 - mach, 3))
def get_exp(self): if isa(self.exp, list): if self.exp[0] is _dict: return dict(zip(*[n.get_exp() for l in self.exp[1:] for n in l])) else: return [n.get_exp() for n in self.exp] else: return self.exp
def analyze_procdef(astnode): exp = astnode.exp if not isa(exp[1].exp, list): procname, args, body = exp[1].exp, exp[2].get_exp(), exp[3:] proc = make_proc(args, body, procname) return CodeObject(astnode, lambda env: env.set(procname, proc(env))) else: procname, args, body = "", exp[1].get_exp(), exp[2:] return CodeObject(astnode, make_proc(args, body, procname))
def get_propulsion_M( h, m, nb ): #calcule la poussée maximale en focntion du nombre de mach, (altitude m, intervalle pour le mach, nombre de points) rho = utils.isa(h)[1] M = np.linspace(m[0], m[1], nb) F = np.array([ avion.F0 * math.pow(rho / rho0, 0.6) * (0.568 + 0.25 * math.pow(1.2 - mach, 3)) for mach in M ]) return F, M
def propulsion_model_mach(X, U, P, mach): ''' même fonction propulsion_model mais avec mach connu qui n'a donc pas à être calculé :param X: vecteur d'état :param U: vecteur de commande :param P: instance de la classe paramètre de l'avion considéré :param mach: nombre de mach :return: ''' p, rho, T = ut.isa(X[s_h]) rho0 = 1.225 return P.F0 * math.pow(rho / rho0, 0.6) * (0.568 + 0.25 * math.pow(1.2 - mach, 3)) * U[i_dth]
def get_aero_forces_and_moments(X, U, P): p, rho, T = ut.isa(X[s_h]) pdyn = 0.5*rho*X[s_va]**2 da = X[s_a]-P.a0 CLw = P.CLa*da at = X[s_a] - 0.25*da + U[i_dm] + P.CLq*P.lt/X[s_va]*X[s_q] CLt = P.St/P.S*P.CLat*at CL = CLw + CLt L = pdyn*P.S*CL D = pdyn*P.S*(P.CD0 + P.ki*CL**2) Cm = P.Cm0 - P.ms*CLw + P.Cmq*P.lt/X[s_va]*X[s_q] + P.Cmd*U[i_dm] M = pdyn*P.S*P.cbar*Cm return L, D, M
def expand(env): if not isa(exp, list): # Like quote, just return the quoted value. return exp elif unquoted(exp): return analyze(exp[1]).exec_(env) else: ret = [] for node in exp: if unquoted_splicing(node.exp): for item in expand_unquoted_splicing(node.exp, env): ret.append(item) else: ret.append(expand_quasiquoted(node.exp)(env)) return ret
def propulsion_model(X, U, P): p, rho, T = ut.isa(X[s_h]) rho0 = 1.225 mach = get_mach(X[s_va], T) return P.F0 * math.pow( rho / rho0, 0.6) * (0.568 + 0.25 * math.pow(1.2 - mach, 3)) * U[i_dth]
def va_of_mach(m, h, k=1.4, Rs=287.05): p, rho, T = ut.isa(h) return m * math.sqrt(k * Rs * T)
# on choisit le point de trim numéro 16 pour lequel on a : h = 3000. mac = 0.8 km = 0.9 ms = 1. # intialisation de l'avion P.set_mass_and_static_margin(km, ms) # km masse avion, ms : marge statique # calcul de va en m/s va = dy.va_of_mach(mac, h) # calcul de rho rho = ut.isa(h)[1] args = {} args['h'] = h args['va'] = dy.va_of_mach(mac, h) # conv mach en m/s X, U = dy.trim(P, args) (A, B) = ut.num_jacobian(X, U, P, dy.dyn) val_propre = np.linalg.eig(A) print(np.real(val_propre[0])) exit() #calcul du nouveau vecteur d'état intial on a alpha #atan(wh/vae) dalpha = math.atan(2./X[dy.s_va])
def get_Cl(): Va = dynamic.va_of_mach(Ma[1], h[1]) PLANE.set_mass_and_static_margin(km[1], ms[1]) rho = utils.isa(h[1])[1] Cl = (PLANE.m * PLANE.g) / (0.5 * rho * PLANE.S * Va**2) return Cl
'h={}, ms={}, km={}'.format(l, i, j), [Ma[0], Ma[1]], 'Ma') ss += 1 plt.show() if __name__ == '__main__': h = [3000, 10000] # altitude en m Ma = [0.4, 0.9] # intervalel nombre de mach ms = [-0.2, 0.5] # marge statique km = [0.1, 1] # coefficient de réglage de la masse nb = 100 # nb de points pour les courbes avion = dynamic.Param_A321() rho0 = utils.isa(0)[1] h1 = np.linspace(h[0], h[1], nb) Ma1 = np.linspace(Ma[0], Ma[1], nb) '''''' '''''' # questions 1-2 # calcul des points de Trim alphatrim = np.zeros((len(ms), len(km), len(Ma), len(h1))) dphrtrim = np.zeros((len(ms), len(km), len(Ma), len(h1))) dthtrim = np.zeros((len(ms), len(km), len(Ma), len(h1))) prop = np.zeros((len(ms), len(km), len(Ma1), len(h))) for ib, i in enumerate(ms): for jb, j in enumerate(km):
# Le trim correspond à une incidence et donc une vitesse, pour une masse donnée de l'avion. # on choisit le point de trim numéro 16 pour lequel on a : h = 11000. mac = 0.8 km = 0.9 ms = 1. # intialisation de l'avion P.set_mass_and_static_margin(km, ms) # km masse avion, ms : marge statique # calcul de va en m/s va = dy.va_of_mach(mac, h) # calcul de rho rho = ut.isa(h)[1] args = {} args['h'] = h args['va'] = dy.va_of_mach(mac, h) # conv mach en m/s X, U = dy.trim(P, args) alpha16 = X[3] # alpha en radians dphr16 = U[0] # delta PHR en radians dth16 = U[1] # thrust de 0 à 1 # calcul de la poussée pour le point de trim 16 F16 = dy.propulsion_model(X, U, P) # calcul de CL16, la val du CL au point de trim16 CL16 = 2 * (P.m * P.g - math.sin(alpha16)) / ((rho * np.power(va, 2) * P.S))
def propulsion_model(X, U, P): p, rho, T = ut.isa(X[s_h]) rho0 = 1.225 mach = get_mach(X[s_va], T) return P.F0 * math.pow(rho / rho0, 0.6) * (0.568 + 0.25 * math.pow(1.2 - mach, 3)) * U[i_dth]
#-*- coding: utf-8 -*- import dynamic, utils import numpy as np import matplotlib.pyplot as plt import math from scipy.integrate import odeint h = [3000.0, 10000.0] #altitude en m Ma = [0.4, 0.9] #intervalel nombre de mach ms = [-0.2, 0.5] #marge statique km = [0.1, 1] #coefficient de réglage de la masse nb = 100 #nb de points pour les courbes avion = dynamic.Param_A321() rho0 = utils.isa(0)[1] '''''' '''''' #calcul des points de Trim alphatrim = np.zeros((len(h), len(Ma), len(ms), len(km))) dphrtrim = np.zeros((len(h), len(Ma), len(ms), len(km))) dthtrim = np.zeros((len(h), len(Ma), len(ms), len(km))) prop = np.zeros((len(h), len(Ma), len(ms), len(km))) for ib, i in enumerate(ms): for jb, j in enumerate(km): avion.set_mass_and_static_margin(j, i) for kb, k in enumerate(Ma): for lb, l in enumerate(h): va_h0 = dynamic.va_of_mach(k, l, k=1.4, Rs=287.05) X, U = dynamic.trim(avion, {'va': va_h0, 'gamm': 0., 'h': l})
# -*- coding: utf-8 -*- import numpy as np, matplotlib.pyplot as plt import utils, dynamic # si le code interprété est dans le fichier courant tuto.py # alors la vraible spéciale __name__ prend la valeur '__main__' # si on utilise tuto.py par importation dans un autre fichier __name__ prend la valeur 'tuto.py' # donc différente de main et le code dans le if ci-dessous n'est pas executé. if __name__ == "__main__": v_Kt = np.array([100, 150, 200]) v_ms = utils.mps_of_kt(v_Kt) print('{} Kt -> {} m/s'.format(v_Kt, v_ms)) h = 5000 p, rho, T = utils.isa(h) print('atmosphère normalisée à {} m: {:.1f} Pa {:.3} kg/m3 {:.2f} K'.format(h, p, rho, T)) hs = np.linspace(0, 10000, 21) # tableau numpy de 21 valeurs de 0 à 10000 m [0, 500, 1000, ... # isa = np.array([utils.isa(h) for h in hs]) # isa(h) renvoie un tuple (p,rho,T) isa(h)[0] sélectionne donc la pression p en pascal # isa est un tableau numpy ; on divise par 100 pour avoir des hpa isa = np.array([utils.isa(h)[0] for h in hs]) / 100 print(isa) plt.plot(hs, isa) # la fonction plot de matplotlib prend le vecteur numpy hs comme coordonnées en abscisse # et le vecteur "isa" pour les valeurs correspodantes en ordonnée plt.xlabel('altitude en m'); plt.ylabel('pression en Hectopascal'); plt.savefig('isa_pressure.png', dpi=120) # sauvegarde du graphe au format png dans le dossier images
def get_aero_forces_and_moments(X, U, P): p, rho, T = ut.isa(X[s_h]) pdyn = 0.5 * rho * X[s_va] ** 2 CL, CD, Cm = get_aero_ceofs(X[s_va], X[s_a], X[s_q], U[i_dm], P) L, D, M = pdyn * P.S * np.array([CL, CD, P.cbar * Cm]) return L, D, M
def va_of_mach(m, h, k=1.4, Rs=287.05): p, rho, T = ut.isa(h) return m * math.sqrt(k * Rs * T)
def read_key(tokens): node = read(tokens) if not isa(node.exp, Symbol) or node.tok[0] != ":": raise SyntaxError("Key formatting error: %s" % node.tok) node.exp = Sym(node.exp[1:]) return node
def get_aero_forces_and_moments(X, U, P): p, rho, T = ut.isa(X[s_h]) pdyn = 0.5 * rho * X[s_va]**2 CL, CD, Cm = get_aero_coefs(X[s_va], X[s_a], X[s_q], U[i_dm], P) L, D, M = pdyn * P.S * np.array([CL, CD, P.cbar * Cm]) return L, D, M
# -*- coding: utf-8 -*- import numpy as np, matplotlib.pyplot as plt import utils, dynamic # si le code interprété est dans le fichier courant tuto.py # alors la vraible spéciale __name__ prend la valeur '__main__' # si on utilise tuto.py par importation dans un autre fichier __name__ prend la valeur 'tuto.py' # donc différente de main et le code dans le if ci-dessous n'est pas executé. if __name__ == "__main__": v_Kt = np.array([100, 150, 200]) v_ms = utils.mps_of_kt(v_Kt) print('{} Kt -> {} m/s'.format(v_Kt, v_ms)) h = 5000 p, rho, T = utils.isa(h) print( 'atmosphère normalisée à {} m: {:.1f} Pa {:.3} kg/m3 {:.2f} K'.format( h, p, rho, T)) hs = np.linspace( 0, 10000, 21) # tableau numpy de 21 valeurs de 0 à 10000 m [0, 500, 1000, ... # isa = np.array([utils.isa(h) for h in hs]) # isa(h) renvoie un tuple (p,rho,T) isa(h)[0] sélectionne donc la pression p en pascal # isa est un tableau numpy ; on divise par 100 pour avoir des hpa isa = np.array([utils.isa(h)[0] for h in hs]) / 100 print(isa) plt.plot( hs, isa
def get_CL_Fmax_trim(aircraft, h, Ma): p, rho, T = ut.isa(h) va = dyn.va_of_mach(Ma, h) pdyn = 0.5*rho*va**2 return P.m*P.g/(pdyn*P.S), propulsion_model([0, h, va, 0, 0, 0], [0, 1, 0, 0], aircraft)
def trainee(h, mac, CDe, P): p, rho, T = ut.isa(h) va = va_of_mach(mac, h) return 0.5 * rho * math.pow(va, 2) * P.S * CDe