def get_max_cl(Re, r): """ Analyze airfoil at a fixed Re, changing aoa from 10 to 15 by 0.1 and returns cl, cd, aoa that makes maximum cl """ xf = XFoil() if r <= 0.175: xf.airfoil = naca6409 else: xf.airfoil = naca2412 xf.Re = Re xf.Re = Re xf.max_iter = 200 xf.n_crit = 9.00 xf.xtr = [1.00, 1.00] xf.M = 0 a_seq, cl_seq, cd_seq, cm_seq, cp_seq = xf.aseq(10, 15, 0.1) # ignore nan by making it 0 cl_seq = np.nan_to_num(cl_seq) # find the maximum cl cl_maxi = np.max(cl_seq) # index of the maximum cl idx = np.argmax(cl_seq) return round(cl_maxi, 2), round(a_seq[idx], 2), round(cd_seq[idx], 2)
def xfoil(): x = request.args.get('x') y = request.args.get('y') Re = float(request.args.get('Re')) M = float(request.args.get('M')) Alpha = float(request.args.get('Alpha')) x = x.split() y = y.split() ctrlX = [float(ele) for ele in x] ctrlY = [float(ele) for ele in y] #bezierX, bezierY = airfoil(ctrlX, ctrlY, 16) xf = XFoil() xf.airfoil = Airfoil(np.array(ctrlX), np.array(ctrlY)) xf.repanel() xf.Re = Re xf.M = 0 xf.max_iter = 100 aero = xf.a(Alpha) xcp, cp = xf.get_cp_distribution() y = savgol_filter(cp, 5, 2) for i in range(30): y = savgol_filter(y, 5, 2) LD = aero[0] / aero[1] vol = PolyArea(ctrlX, ctrlY) return jsonify(result=str(round(aero[0], 3)) + " " + str(round(aero[1], 3)) + " " + str(round(aero[2], 3)) + " " + str(round(LD, 2)) + " " + str(round(vol, 3)), xcp=xcp.tolist(), cp=y.tolist())
def get_cls(coords): xf = XFoil() xf.print = False cl_s = [] for coord in coords: cl = get_cl(coord, xf) cl_s.append(cl) return np.array(cl_s)
def evaluate(self, individual): ratios = self.decoder(individual, self.code_division) datlist_list = [fc.read_datfile(file) for file in self.datfiles] datlist_shaped_list = [ fc.shape_dat(datlist) for datlist in datlist_list ] newdat = fc.interpolate_dat(datlist_shaped_list, ratios) foil_para = fc.get_foil_para(newdat) datx = np.array([ax[0] for ax in newdat]) daty = np.array([ax[1] for ax in newdat]) newfoil = Airfoil(x=datx, y=daty) mt, mta, mc, mca, s = foil_para penalty = 0 for g, p in zip(self.gs, self.penalties): if (not g): penalty += p xf = XFoil() xf.airfoil = newfoil xf.Re = self.re xf.max_iter = 60 print(self.assigns, self.datfiles) scope = locals() exec(self.assigns, scope) #---------------------------------- #目的値 #---------------------------------- try: obj1, obj2, obj3 = [eval(o) for o in self.Os] except IndexError as e: obj1, obj2, obj3 = [1.0] * self.NOBJ traceback.print_exc() except SyntaxError as e: raise ValueError("invalid objection") if (np.isnan(obj1) or obj1 > 1): obj1 = 1 if (np.isnan(obj2) or obj2 > 1): obj2 = 1 if (np.isnan(obj3) or obj3 > 1): obj3 = 1 obj1 += penalty obj2 += penalty obj3 += penalty return [obj1, obj2, obj3]
def initialize(self): super().initialize() self.options.declare("print", default=False, types=bool) xf = XFoil() xf.print = False self.options.declare("_xf", default=xf, types=XFoil, allow_none=True) self.options.declare("_pool", default=ThreadPool(processes=1), types=ThreadPool, allow_none=True) self.recording_options["options_excludes"] = ["_xf", "_pool"]
def get_torque(angular_velocity): torque_sum_small = 0 torque_sum_large = 0 w = angular_velocity for key, value in dfdict.items(): value["blade_velocity"] = value['r_position'] * w value["relative_velocity"] = round( math.sqrt(value["blade_velocity"]**2 + value["wind_velocity"]**2), 2) value["arctan"] = math.degrees( math.atan2(value["wind_velocity"], value["blade_velocity"])) aoa = round(value["arctan"] - value["pitch_angle"], 2) value["angle_of_attack"] = aoa re_n = round( value["relative_velocity"] * value["chord_length"] / 0.00001511, 3) value["Reynolds_number"] = re_n xf = XFoil() if key < 13: xf.airfoil = naca6409 else: xf.airfoil = naca2412 xf.Re = re_n xf.max_iter = 100 xf.n_crit = 9.00 xf.xtr = [1.00, 1.00] xf.M = 0 value["Cl"], value["Cd"], value["Cm"], value["Cp"] = xf.a(aoa) force_reference = 0.5 * density * value["relative_velocity"]**2 if math.isnan(value["Cl"]): value["torque"] = 0 else: lift = value["Cl"] * force_reference * 0.0125 * value[ 'chord_length'] drag = value["Cd"] * force_reference * 0.0125 * value[ 'chord_length'] value["torque"] = value["r_position"] * ( lift * math.sin(math.radians(value["pitch_angle"])) - drag * math.cos(math.radians(value["pitch_angle"]))) if key < 13: torque_sum_small += value["torque"] else: pass if key > 0: torque_sum_large += value["torque"] else: pass df2 = pd.DataFrame.from_dict(dfdict, orient="index") df_collection.append(df2) torque_sum_avg = 0.5 * (torque_sum_small + torque_sum_large) return torque_sum_avg
def __init__(self): self.xf = XFoil() self.min_action = np.array([0.1, 0.05, 1.0, 0.05, 0.4, 1.0, 0.0]) self.max_action = np.array([0.4, 0.4, 3.0, 3.0, 8.0, 10.0, 10.0]) ''' 測試開始, 可省略測試''' # (.01, .4), (.05, .4), (1, 3), (0.05, 3), (0.4, 8), (1, 10) # self.xf.airfoil = naca0012 # k = [0.08813299, 0.28250898, 2.80168427, 2.56204214, 1.48703742, 8.53824561] # k = [0.34422, 0.38976, 1.1, 2.9989, 1.6071, 9.9649] k = [0.1584, 0.1565, 2.1241, 1.8255, 11.6983, 3.827] # org # k = [0.1784, 0.1365, 2.1201, 1.8057, 3.8071, 11.7009] # k = [0.1472, 0.1638, 2.1041, 1.8156, 3.8141, 11.6808] # k = [0.1784, 0.1365, 2.1201, 1.8057, 3.8071, 11.7009] # k = [0.1783, 0.1366, 2.1283, 1.8073, 3.8325, 11.7176] # k = [0.25840, 0.14474, 2.22410, 1.92550, 11.59984, 3.92623] airfoil = construct_airfoil(*k) x, y = get_coords_plain(airfoil._spline(100)) self.xf.airfoil = Airfoil(x=x, y=y) # test_airfoil = NACA4(2, 3, 15) # a = test_airfoil.max_thickness() # self.xf.airfoil = test_airfoil.get_coords() self.xf.Re = 1e6 self.xf.M = 0.04 self.xf.print = False cl, cd, cm, cp = self.xf.a(9) x = np.array(x, dtype='float32') y = np.array(y, dtype='float32') reward = cl / cd # reward = cl ''' 測試結束, 可省略測試''' # cl, cd, cm, cp = self.xf.a(12.2357) # self.action_space = spaces.Discrete(30) self.action_space = spaces.Box(self.min_action, self.max_action, dtype=np.float32) # high = np.array([100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0]) high = np.array([ 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0 ]) self.observation_space = spaces.Box( -high, high, dtype=np.float32) #創建state大小(25,f22機翼,b3cl.cd.aoa) self.seed() self.viewer = None self.state = None self.steps_beyond_done = None
def cl_visc_analysis(airfoil, cl_i, cl_f, cl_step, re, mach, max_iter, id): """Viscous analysis over range of lift coefficients.""" # Initializes airfoil and assigns NACA xf = XFoil() xf.naca(airfoil) xf.max_iter = max_iter xf.Re = re xf.M = mach # Collects values a, cl, cd, cm, cp = xf.cseq(cl_i, cl_f, cl_step) x, cp_0 = xf.get_cp_distribution() # Plots all the data plot(a, cl, cd, cm, cp, x, cp_0, id)
def alpha_visc_analysis(airfoil, alpha_i, alpha_f, alpha_step, re, mach, max_iter, id): """Viscous analysis over range of angle of attacks.""" # Initializes airfoil and assigns NACA xf = XFoil() xf.naca(airfoil) xf.max_iter = max_iter xf.Re = re xf.M = mach # Collects values a, cl, cd, cm, cp = xf.aseq(alpha_i, alpha_f, alpha_step) x, cp_0 = xf.get_cp_distribution() # Plots all the data plot(a, cl, cd, cm, cp, x, cp_0, id)
def cl_inv_analysis(airfoil, cl_i, cl_f, cl_step, max_iter, id): """Inviscid analysis over range of angle of attacks.""" # Initializes airfoil and assigns NACA xf = XFoil() xf.naca(airfoil) xf.max_iter = max_iter # Collects values a, cl, cd, cm, cp = xf.cseq(cl_i, cl_f, cl_step) x, cp_0 = xf.get_cp_distribution() # Plots all the data plot(a, cl, cd, cm, cp, x, cp_0, id)
def get_cl(coord, xf=None, angle=5): if xf is None: xf = XFoil() xf.print = False xf.Re = 3e6 xf.max_iter = 100 datax, datay = coord.reshape(2, -1) xf.airfoil = Airfoil(x=datax, y=datay) c = xf.a(angle) cl= c[0] return cl
def getCoefficients(naca, reynolds=1e6, iterations=20, angle=10, angle_step=.5): xf = XFoil() xf.naca(f"{naca:04d}") xf.Re = reynolds xf.max_iter = 20 a, cl, cd, cm, cp = xf.aseq(0, angle, .5) ratio = cl / cd max_idx = np.nanargmax(ratio) return (ratio[max_idx], a[max_idx]), a, cl, cd, max_idx
def evaluate(self,individual): DELTA = 1e10 #---------------------------------- #遺伝子に基づいて新翼型を生成 #---------------------------------- #遺伝子に基づきスプライン翼型を作成 x = individual[:int(len(individual)/2)] x.insert(0,1.0) x.insert(int(len(x)/2)+1,0.0) x.append(1.0) y = individual[int(len(individual)/2):] if not (all([u - d > 0 for u, d in zip(y[:int(len(y)/2)], y[int(len(y)/2):])]) or all([u - d < 0 for u, d in zip(y[:int(len(y)/2)], y[int(len(y)/2):])])): print("crossed") return [DELTA*10]*self.NOBJ y.insert(0,0.0) y.insert(int(len(y)/2)+1,0.0) y.append(0.0) newdat = fc.spline_foil(x, y, 200) shape_dat = fc.shape_dat([[a, b] for a, b in zip(newdat[0][::-1], newdat[1][::-1])]) #翼型の形に関する情報を取得する foil_para = fc.get_foil_para(shape_dat) mt, mta, mc, mca, s, crossed, bd, bt, bc, smooth, td = foil_para # mt: 最大翼厚(百分率) # mta: 最大翼厚位置(百分率) # mc: 最大キャンバー(百分率) # mca: 最大きゃんばー位置(百分率) # s: 翼型の下面における、最大y座標-最小y座標 # crossed: 翼型が交差しているならTrue,それ以外ならFalse # bd: 翼型の粗さ(大きいほど粗い) # bt: 翼厚分布の粗さ(大きいほど粗い) # bc: キャンバー分布の粗さ(大きいほど粗い) # smooth: 無視 # td: 翼厚分布 if crossed: print("crossed_a") return [DELTA*10]*self.NOBJ else: print("hi_a") #新しい翼型をAerofoilオブジェクトに適用 datx = np.array(newdat[0][::-1]) daty = np.array(newdat[1][::-1]) newfoil = Airfoil(x = datx, y = daty) #翼型の形に関する拘束条件 penalty = 0 if not all([t >= 0.0035 for t in td[10:80]]): penalty += 100 * (sum([abs(t - 0.0035)*10 for t in td[15:85] if t - 0.0035 < 0])) if not all([t <= 0.015 for t in td[:15]]): penalty += 100 * (sum([abs(t - 0.015)*10 for t in td[:15] if t > 0.015])) if mta > 0.4: penalty += 100 * (mta - 0.4) if mc < 0.0: penalty += 100 * (-mc) if datx[0] > 1.002 or datx[0] < 0.998: print("invalid foil") return [DELTA*10]*self.NOBJ #---------------------------------- #新翼型の解析 #---------------------------------- try: xf = XFoil() #レイノルズ数の設定 xf.airfoil = newfoil xf.Re = self.re xf.print = False xf.max_iter = 40 #xf.polar = "polar" + id #境界要素法計算時1ステップにおける計算回数 #xf.repanel(n_nodes = 180) #計算結果格納 #result = xf.OneAlpha() cl, cd, cm, cp = xf.a(5.0) #---------------------------------- #目的値 #---------------------------------- if cl >= 0: obj1 = 1/cl else: obj1 = self.delta obj2 = cd except Exception as e: obj1,obj2=[DELTA]*self.NOBJ traceback.print_exc() if (np.isnan(obj1)): obj1 = DELTA if (np.isnan(obj2)): obj2 = DELTA return [obj1 + penalty, obj2 + penalty]
a_p_a = a_p v_r = math.sqrt(v_1 ** 2 * (1 - a_max) ** 2 + prop_omega ** 2 * r ** 2 * (a_p_max - 1) ** 2) # ITERATION & CALL TO XFOIL c_l = cl_i if c = (a_max * 8 * pi * r * math.sin(phi) ** 2) / ((1 - a_max) * prop_blades * c_l * math.cos(phi)) re = (v_r * c) / (nu_mars) # XFOIL ####### from xfoil import XFoil xf = XFoil() # Import an airfoil from xfoil.test import XXXXX xf.airfoil = XXXXX # Setting up the analysis parameters xf.Re = re xf.max_iter = 100 xf.M = 0.7 # Obtaining the angle of attack, lift coefficient, drag coefficient and momentum coefficient of the airfoil a, cl, cd, cm = xf.aseq(0, 30, 0.5)
def analyze_airfoil(x, y_u, y_l, cl, rey, mach=0, xf=None, pool=None, show_output=False): """ Analyze an airfoil at a given lift coefficient for given Reynolds and Mach numbers using XFoil. Parameters ---------- x : array_like Airfoil x-coordinates y_u, y_l : array_like Airfoil upper and lower curve y-coordinates cl : float Target lift coefficient rey, mach : float Reynolds and Mach numbers xf : XFoil, optional An instance of the XFoil class to use to perform the analysis. Will be created if not given pool : multiprocessing.ThreadPool, optional An instance of the multiprocessing.Threadpool class used to run the xfoil_worker. Will be created if not given show_output : bool, optional If True, a debug string will be printed after analyses. False by default. Returns ------- cd, cm : float or np.nan Drag and moment coefficients of the airfoil at specified conditions, or nan if XFoil did not run successfully """ # If the lower and upper curves swap, this is a bad, self-intersecting airfoil. Return 1e27 immediately. if np.any(y_l > y_u): return np.nan else: clean_xf = False if xf is None: xf = XFoil() xf.print = show_output clean_xf = True clean_pool = False if pool is None: pool = ThreadPool(processes=1) clean_pool = True xf.airfoil = Airfoil(x=np.concatenate((x[-1:0:-1], x)), y=np.concatenate((y_u[-1:0:-1], y_l))) xf.Re = rey xf.M = mach xf.max_iter = 100 xf.n_crit = 0.1 cd, cm = pool.apply(xfoil_worker, args=(xf, cl)) if clean_xf: del xf if clean_pool: del pool return cd, cm, None if clean_xf else xf
ax.yaxis.set_minor_locator(ticker.MultipleLocator(mult_y / 5 * Y_0)) if (grd == True): ax.grid(b=True, which='major', axis='both') else: ax.grid(b=False, which='major', axis='both') if (minorgrd == True): ax.grid(b=True, which='minor', axis='both') else: ax.grid(b=False, which='minor', axis='both') if (x_lim != None): ax.set_xlim(x_lim) if (y_lim != None): ax.set_ylim(y_lim) return ax """#########################################################################""" from xfoil.test import naca0012 from xfoil import XFoil xf = XFoil() xf.airfoil = naca0012 xf.Re = 1e5 xf.max_iter = 20 a, cl, cd, cm, co = xf.aseq(-20, 20, 1) fig, axarr = plt.subplots(1, 1, figsize=(6, 4)) axarr.plot(a, cl) plt.show()
#!/usr/bin/python3 from xfoil import XFoil import matplotlib.pyplot as plt xf = XFoil() xf.load("revclarky.dat") xf.Re = 1e5 xf.M = 0 xf.max_iter = 100 a, cl, cd, cm, cp = xf.aseq(-2, 2, 0.5) plt.plot(a, cl) plt.title("alfa vs cl") plt.show() #plt.plot(xf.airfoil.x,xf.airfoil.y) #plt.axis('equal') #plt.show()
def saveResults(): drag = Aerofoils_obj.cd * 0.5 * rho * (velocity**2) * mac * span datarow = [span, chord, drag] with open(r'viscous_drag_landscape_results.csv', 'a', newline='') as f: writer = csv.writer(f) writer.writerow(datarow) rho = 1.1685 velocity = 41.6667 g = 9.81 reynolds_div_chord = 2794120 mass = 100 xf = XFoil() xf.max_iter = 100 print("Max iterations: {0}\nMass: {1}Kg".format(xf.max_iter, mass)) START_CHORD = 0.1 END_CHORD = 0.3 CHORD_POINTS_PER_METRE = 100 START_SPAN = 8 END_SPAN = 10 SPAN_POINTS_PER_METRE = 10 chord_points = int((END_CHORD - START_CHORD) * CHORD_POINTS_PER_METRE) chord_increment = float((END_CHORD - START_CHORD) / chord_points)
from xfoil import XFoil import matplotlib.pyplot as plt xf = XFoil() xf.load("clarky.dat") plt.plot(xf.airfoil.x, xf.airfoil.y) plt.axis('equal') plt.show()
aoa_h = 34 fig, ax = plt.subplots(1, 1, figsize=(9, 8)) klist = [1] for k in range(1): print(k) x = aifoils[k]['x'].values y = aifoils[k]['y'].values ang_low = -32 ang_high = 32 ang_spacing = 2 xfc = XFoil() xfc.airfoil = Airfoil(x, y) xfc.Re = re[k] xfc.max_iter = 40 ac, clc, cdc, cmc, cpminc = xfc.aseq(ang_low, ang_high, ang_spacing) df = aifoils_cfd[k].where(aifoils_cfd[k]['alpha [deg]'] >= aoa_l) df = df.where(aifoils_cfd[k] <= aoa_h) df = df.dropna() #.values cl_panel = [] cdp_panel = [] for aoa in df['alpha [deg]']: data_xy = aifoils[k].values CL, CDP, Cp, pp = panel(data_xy[:, :], alfader=aoa)
#1. Define Aero and Structural grid Nel_struct = 6 # Number of elements per surface in struct grid Nel_aero = 30 # Number of elements per surface in aero grid Xwing_aero = Aero.NACA4(1.0, 0.12, 0.03, 0.4, Nel_aero) #create aero grid nodes Xwing_struct = Aero.NACA4(1.0, 0.12, 0.03, 0.4, Nel_struct) #create aero grid nodes Xwing_aero1 = Aero.NACA4(1.0, 0.13, 0.03, 0.3, Nel_aero) #create aero grid nodes Xwing_struct1 = Aero.NACA4(1.0, 0.13, 0.03, 0.3, Nel_struct) #create aero grid nodes xf = XFoil() aa = Xwing_aero1[:, 0] b = Xwing_aero1[:, 1] archive3 = open('lt.txt', 'w') for line in range(len(aa)): aux = [aa[line], b[line]] string = str(aux).replace("[", " ").replace(",", " ").replace("]", " ").replace("'", " ") archive3.writelines(string + '\n') aux.clear # Calculates the aerodynamic coeff using Xfoil archive3.close()
def evaluate(individual): global code_division #---------------------------------- #遺伝子にも続いて新翼型を生成 #---------------------------------- #遺伝子をデコード ratios = decoder(individual, code_division) #遺伝子に基づき翼型を混合して、新しい翼型を作る datlist_list = [fc.read_datfile(file) for file in datfiles] datlist_shaped_list = [fc.shape_dat(datlist) for datlist in datlist_list] newdat = fc.interpolate_dat(datlist_shaped_list,ratios) #翼型の形に関する情報を取得する #foilpara == [最大翼厚、最大翼厚位置、最大キャンバ、最大キャンバ位置、S字の強さ] foil_para = fc.get_foil_para(newdat) #新しい翼型をAerofoilオブジェクトに適用 datx = np.array([ax[0] for ax in newdat]) daty = np.array([ax[1] for ax in newdat]) newfoil = Airfoil(x = datx, y = daty) mt, mta, mc, mca, s = foil_para #---------------------------------- #翼の形に関する拘束条件 #---------------------------------- penalty = 0 print('===================') if(mc<0): print("out of the border") print("reverse_cmaber") penalty -= mc if(mt<0.08): print("out of the border") print("too_thin") penalty += 0.08-mt if(mt>0.11): print("out of the border") print("too_fat") penalty += mt-0.11 #if(foil_para[4]>0.03): # print("out of the border") # print("peacock") # print('===================') # return (1.0+(foil_para[4]-0.03),)*NOBJ if(mta<0.23): print("out of the border") print("Atama Dekkachi!") penalty += 0.23 - mta if(mta>0.3): print("out of the border") print("Oshiri Dekkachi!") penalty += mta - 0.3 #---------------------------------- #新翼型の解析 #---------------------------------- xf = XFoil() xf.airfoil = newfoil #レイノルズ数の設定 xf.Re = 1.5e5 #境界要素法計算時1ステップにおける計算回数 xf.max_iter = 60 #座標整形 xf.repanel(n_nodes = 300) xf.print = False #計算結果格納 a, cl, cd, cm, cp = xf.cseq(0.4, 1.1, 0.1) lr = [l/d for l, d in zip(cl,cd)] #---------------------------------- #目的値 #---------------------------------- try: #揚抗比の逆数を最小化 obj1 = 1/lr[1] #揚抗比のピークを滑らかに(安定性の最大化) maxlr = max(lr) maxlr_index = lr.index(maxlr) obj2 = abs(maxlr - lr[maxlr_index+1]) #下面の反りを最小化(製作再現性の最大化) obj3 = foil_para[4] except Exception as e: obj1,obj2,obj3=[1.0]*NOBJ traceback.print_exc() if (np.isnan(obj1) or obj1 > 1): obj1 = 1 if (np.isnan(obj2) or obj2 > 1): obj2 = 1 if (np.isnan(obj3) or obj3 > 1): obj3 = 1 obj1 += penalty obj2 += penalty obj3 += penalty print("individual",individual) print("evaluate",obj1,obj2,obj3) print("max_thickness",foil_para[0]) print("at",foil_para[1]) print("max_camber",foil_para[2]) print("at",foil_para[3]) print("S",foil_para[4]) print('===================') return [obj1, obj2, obj3]
def evaluate(self, individual): #解析が発散した際の評価値 DELTA = 1e10 #---------------------------------- #遺伝子に基づいて新翼型を生成 #---------------------------------- #遺伝子をデコード ratios = self.decoder(individual, self.code_division) #遺伝子に基づき翼型を混合して、新しい翼型を作る datlist_list = [fc.read_datfile(file) for file in self.datfiles] datlist_shaped_list = [ fc.shape_dat(datlist) for datlist in datlist_list ] newdat = fc.interpolate_dat(datlist_shaped_list, ratios) #翼型の形に関する情報を取得する mt, mta, mc, mca, s, crossed, bd, bt, bc, smooth, td = fc.get_foil_para( newdat) #新しい翼型をAerofoilオブジェクトに適用 datx = np.array([ax[0] for ax in newdat]) daty = np.array([ax[1] for ax in newdat]) newfoil = Airfoil(x=datx, y=daty) #---------------------------------- #翼の形に関する拘束条件 #---------------------------------- penalty = 0 #キャンバに関する拘束条件 if (mc < 0): penalty -= mc #最大翼厚に関する拘束条件 if (mt < 0.08): penalty += 0.08 - mt if (mt > 0.11): penalty += mt - 0.11 #最大翼厚位置に関する拘束条件 if (mta < 0.23): penalty += 0.23 - mta if (mta > 0.3): penalty += mta - 0.3 #---------------------------------- #新翼型の解析 #---------------------------------- xf = XFoil() xf.airfoil = newfoil #レイノルズ数の設定 xf.Re = self.re #境界要素法計算時1ステップにおける計算回数 xf.max_iter = 60 xf.print = False #計算結果格納 a, cl, cd, cm, cp = xf.cseq(0.4, 1.1, 0.1) #---------------------------------- #目的値 #---------------------------------- try: #揚抗比の逆数を最小化 obj1 = 1 / lr[1] #揚抗比のピークを滑らかに(安定性の最大化) maxlr = max(lr) maxlr_index = lr.index(maxlr) obj2 = abs(maxlr - lr[maxlr_index + 1]) #下面の反りを最小化(製作再現性の最大化) obj3 = s except Exception as e: obj1, obj2, obj3 = [DELTA] * self.NOBJ traceback.print_exc() if (np.isnan(obj1) or obj1 > 1): obj1 = DELTA if (np.isnan(obj2) or obj2 > 1): obj2 = DELTA if (np.isnan(obj3) or obj3 > 1): obj3 = DELTA obj1 += penalty obj2 += penalty obj3 += penalty return [obj1, obj2, obj3]
def feature_xfoil(cst_u, cst_l, t, Minf: float, Re, AoA, n_crit=0.1, fname='feature-xfoil.txt'): ''' Evaluate by xfoil and extract features. Inputs: --- cst-u, cst-l: list of upper/lower CST coefficients of the airfoil. \n t: airfoil thickness or None \n Minf: free stream Mach number for wall Mach number calculation \n Re, AoA (deg): flight condition (s), float or list, for Xfoil \n n_crit: critical amplification ratio for transition in xfoil \n fname: output file name. If None, then no output \n ### Dependencies: cst-modeling3d, xfoil ''' from cst_modeling.foil import cst_foil from xfoil import XFoil from xfoil.model import Airfoil #TODO: Build foil #! 201 is the maximum amount of points that xfoil can handle #! tail = 0.001 is to avoid point overlap xx, yu, yl, t0, R0 = cst_foil(201, cst_u, cst_l, x=None, t=t, tail=0.001) #! xfoil do not support leading edge of (0,0) on both upper and lower surface x = np.array(list(reversed(xx[1:])) + xx[1:]) y = np.array(list(reversed(yu[1:])) + yl[1:]) foil = Airfoil(x, y) #TODO: Xfoil xf = XFoil() xf.print = False xf.airfoil = foil xf.max_iter = 40 #* Transition by power law xf.n_crit = n_crit #TODO: Xfoil calculation if not isinstance(Re, list): Re = [Re] AoA = [AoA] n = len(Re) for i in range(n): xf.reset_bls() if Re[i] is not None: xf.Re = Re[i] cl, cd, cm, cp = xf.a(AoA[i]) x, cp = xf.get_cp_distribution() print(xf.Re, AoA[i], cl) #* Extract features fF = PhysicalXfoil(Minf, AoA[i], Re[i]) fF.setdata(x, y, cp) fF.extract_features() #* Output if fname is None: continue if i == 0: f = open(fname, 'w') else: f = open(fname, 'a') f.write('\n') f.write('%10s %15.6f \n' % ('Minf', Minf)) f.write('%10s %15.6f \n' % ('AoA', AoA[i])) f.write('%10s %15.6f \n' % ('Re', Re[i] / 1e6)) f.write('%10s %15.6f \n' % ('CL', cl)) f.write('%10s %15.6f \n' % ('Cd', cd)) f.write('%10s %15.6f \n' % ('Cm', cm)) f.close() fF.output_features(fname=fname, append=True)
from xfoil import XFoil from xfoil.test import naca0012 xf = XFoil() xf.airfoil = naca0012 xf.Re = 1e6 xf.max_iter = 40 a, cl, cd, cm, co = xf.aseq(-20, 20, 0.5)
def total_dict(angular_velocity): torque_sum = 0 w = angular_velocity for key, value in dfdict.items(): value["blade_velocity"] = value['r_position'] * w value["relative_velocity"] = round( math.sqrt(value["blade_velocity"]**2 + value["wind_velocity"]**2), 2) value["arctan"] = math.degrees( math.atan2(value["wind_velocity"], value["blade_velocity"])) aoa = round(value["arctan"] - value["pitch_angle"], 1) value["angle_of_attack"] = aoa re_n = round(value["relative_velocity"] * value["chord_length"] / 0.00001511) value["Reynolds_number"] = re_n xf = XFoil() if key < 13: xf.airfoil = naca6409 else: xf.airfoil = naca2412 xf.Re = round(re_n / 100) * 100 xf.max_iter = 200 xf.n_crit = 9.00 xf.xtr = [1.00, 1.00] xf.M = 0 c_l, c_d, c_m, c_p = xf.a(aoa) force_reference = 0.5 * density * value["relative_velocity"]**2 if math.isnan(c_l): pass else: value["Cl"] = c_l value["Cd"] = c_d value["Cm"] = c_m value["Cp"] = c_p lift = c_l * force_reference * 0.0125 * value['chord_length'] drag = c_d * force_reference * 0.0125 * value['chord_length'] value["lift"] = lift value["drag"] = drag # value["torque"] = value["r_position"] * lift * math.sin(math.radians(value["pitch_angle"])) torque = value["r_position"] * ( lift * math.sin(math.radians(value["pitch_angle"])) - drag * math.cos(math.radians(value["pitch_angle"]))) value["torque"] = torque torque_sum += torque xf.reset_bls() # detailed_df = pd.DataFrame.from_dict(dfdict, orient="index") # print(detailed_df) print(torque_sum, angular_velocity) return dfdict, torque_sum
def evaluate(self,individual): #---------------------------------- #遺伝子に基づいて新翼型を生成 #---------------------------------- #遺伝子をデコード ratios = self.decoder(individual, self.code_division) #遺伝子に基づき翼型を混合して、新しい翼型を作る datlist_list = [fc.read_datfile(file) for file in self.datfiles] datlist_shaped_list = [fc.shape_dat(datlist) for datlist in datlist_list] newdat = fc.interpolate_dat(datlist_shaped_list,ratios) #翼型の形に関する情報を取得する #foilpara == [最大翼厚、最大翼厚位置、最大キャンバ、最大キャンバ位置、S字の強さ] foil_para = fc.get_foil_para(newdat) #新しい翼型をAerofoilオブジェクトに適用 datx = np.array([ax[0] for ax in newdat]) daty = np.array([ax[1] for ax in newdat]) newfoil = Airfoil(x = datx, y = daty) mt, mta, mc, mca, s = foil_para #---------------------------------- #翼の形に関する拘束条件 #---------------------------------- """ penalty = 0 for g, p in zip(self.gs, self.penalties): if(not g): penalty += p """ penalty = 0 print('===================') if(mc<0): print("out of the border") print("reverse_cmaber") penalty -= mc if(mt<0.08): print("out of the border") print("too_thin") penalty += 0.08-mt if(mt>0.11): print("out of the border") print("too_fat") penalty += mt-0.11 #if(foil_para[4]>0.03): # print("out of the border") # print("peacock") # print('===================') # return (1.0+(foil_para[4]-0.03),)*NOBJ if(mta<0.23): print("out of the border") print("Atama Dekkachi!") penalty += 0.23 - mta if(mta>0.3): print("out of the border") print("Oshiri Dekkachi!") penalty += mta - 0.3 #---------------------------------- #新翼型の解析 #---------------------------------- xf = XFoil() xf.airfoil = newfoil #レイノルズ数の設定 xf.Re = self.re #境界要素法計算時1ステップにおける計算回数 xf.max_iter = 60 #print("hi") #print(vars) #scope = locals() #var0, var1, var2, var3, var4, var5, var6, var7 = [0 if var == None or var == '' else eval(var,scope) for var in self.vars] #計算結果格納 a, cl, cd, cm, cp = xf.cseq(0.4, 1.1, 0.1) lr = [l/d for l, d in zip(cl,cd)] #---------------------------------- #目的値 #---------------------------------- """ try: obj1,obj2,obj3 = [eval(o) for o in Os] except Exception as e: obj1,obj2,obj3=[1.0]*self.NOBJ traceback.print_exc() """ try: #揚抗比の逆数を最小化 obj1 = 1/lr[1] #揚抗比のピークを滑らかに(安定性の最大化) maxlr = max(lr) maxlr_index = lr.index(maxlr) obj2 = abs(maxlr - lr[maxlr_index+1]) #下面の反りを最小化(製作再現性の最大化) obj3 = s except Exception as e: obj1,obj2,obj3=[1.0]*self.NOBJ traceback.print_exc() if (np.isnan(obj1) or obj1 > 1): obj1 = 1 if (np.isnan(obj2) or obj2 > 1): obj2 = 1 if (np.isnan(obj3) or obj3 > 1): obj3 = 1 obj1 += penalty obj2 += penalty obj3 += penalty return [obj1, obj2, obj3]
if not use_dataset: npz = np.load(input_path) labels = npz[npz.files[0]] coords = npz[npz.files[1]] else: perfs_npz = np.load("./dataset/standardized_perfs.npz") coords_npz = np.load("./dataset/standardized_coords.npz") coords = coords_npz[coords_npz.files[0]] coord_mean = coords_npz[coords_npz.files[1]] coord_std = coords_npz[coords_npz.files[2]] perfs = perfs_npz[perfs_npz.files[0]] perf_mean = perfs_npz[perfs_npz.files[1]] perf_std = perfs_npz[perfs_npz.files[2]] xf = XFoil() xf.print = False cnt = 0 print("start calculating!") start = time.time() coords = coords*coord_std+coord_mean if use_dataset else coords for label, coord in zip(labels, coords): cl = get_cl(xf, coord) if not np.isnan(cl): cnt+=1 if type(label) is np.float64: label = str(round(label, 3)) else: label = str(round(label[0],3)) print("label: {0}, cl: {1}".format(label, cl))
class XFoilEnv(gym.Env): """ Description: A pole is attached by an un-actuated joint to a cart, which moves along a frictionless track. The pendulum starts upright, and the goal is to prevent it from falling over by increasing and reducing the cart's velocity. Source: This environment corresponds to the version of the cart-pole problem described by Barto, Sutton, and Anderson Observation: Type: Box(4) Num Observation Min Max 0 Cart Position -4.8 4.8 1 Cart Velocity -Inf Inf 2 Pole Angle -24 deg 24 deg 3 Pole Velocity At Tip -Inf Inf Actions: Type: Discrete(2) Num Action 0 Push cart to the left 1 Push cart to the right Note: The amount the velocity that is reduced or increased is not fixed; it depends on the angle the pole is pointing. This is because the center of gravity of the pole increases the amount of energy needed to move the cart underneath it Reward: Reward is 1 for every step taken, including the termination step Starting State: All observations are assigned a uniform random value in [-0.05..0.05] Episode Termination: Pole Angle is more than 12 degrees Cart Position is more than 2.4 (center of the cart reaches the edge of the display) Episode length is greater than 200 Solved Requirements Considered solved when the average reward is greater than or equal to 195.0 over 100 consecutive trials. """ metadata = { 'render.modes': ['human', 'rgb_array'], 'video.frames_per_second' : 50 } def __init__(self): self.xf = XFoil() self.min_action = np.array([0.1, 0.05, 1.0, 0.05, 0.4, 1.0, 0.0]) self.max_action = np.array([0.4, 0.4, 3.0, 3.0, 8.0, 10.0, 10.0]) ''' 測試開始, 可省略測試''' # (.01, .4), (.05, .4), (1, 3), (0.05, 3), (0.4, 8), (1, 10) # self.xf.airfoil = naca0012 # k = [0.08813299, 0.28250898, 2.80168427, 2.56204214, 1.48703742, 8.53824561] # k = [0.34422, 0.38976, 1.1, 2.9989, 1.6071, 9.9649] k = [0.1584, 0.1565, 2.1241, 1.8255, 11.6983, 3.827] # org # k = [0.1784, 0.1365, 2.1201, 1.8057, 3.8071, 11.7009] # k = [0.1472, 0.1638, 2.1041, 1.8156, 3.8141, 11.6808] # k = [0.1784, 0.1365, 2.1201, 1.8057, 3.8071, 11.7009] # k = [0.1783, 0.1366, 2.1283, 1.8073, 3.8325, 11.7176] # k = [0.25840, 0.14474, 2.22410, 1.92550, 11.59984, 3.92623] airfoil = construct_airfoil(*k) x, y = get_coords_plain(airfoil._spline(100)) self.xf.airfoil = Airfoil(x=x, y=y) # test_airfoil = NACA4(2, 3, 15) # a = test_airfoil.max_thickness() # self.xf.airfoil = test_airfoil.get_coords() self.xf.Re = 1e6 self.xf.M = 0.04 self.xf.print = False cl, cd, cm, cp = self.xf.a(9) x = np.array(x, dtype='float32') y = np.array(y,dtype='float32') # reward = cl/cd reward = cl ''' 測試結束, 可省略測試''' # cl, cd, cm, cp = self.xf.a(12.2357) # self.action_space = spaces.Discrete(30) self.action_space = spaces.Box(self.min_action, self.max_action, dtype=np.float32) # high = np.array([100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0]) high = np.array([100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0]) self.observation_space = spaces.Box(-high, high, dtype=np.float32) #創建state大小(25,f22機翼,b3cl.cd.aoa) self.seed() self.viewer = None self.state = None self.steps_beyond_done = None def seed(self, seed=None): self.np_random, seed = seeding.np_random(seed) return [seed] def step(self, action): # assert self.action_space.contains(action), "%r (%s) invalid"%(action, type(action)) ''' action 包含 6 個機翼形狀控制參數以及 1 個攻角''' angular = action[6] k = action[0:6] '''將機翼控制座標傳入 airfoil, 並計算翼面之座標''' airfoil = construct_airfoil(*k) x, y = get_coords_plain(airfoil._spline(100)) '''將座標傳入 xfoil ''' self.xf.airfoil = Airfoil(x=x, y=y) # state = self.state self.xf.Re = 1e6 self.xf.M = 0.04 '''計算 cl, cd, cm, cp 當角度為 angular 時''' cl, cd, cm, cp = self.xf.a(angular) '''如果結果不穩定, 有無限大之值, 重設 state''' if np.isnan(cl) or np.isnan(cd) or np.isnan(cm) or np.isnan(cp): reward = -10.0 # self.state = self.reset() done = 0 else: '''如果結果穩定, 結束這個 weight 的計算''' '''升力最佳或升阻比最佳在此設定''' # reward = cl/cd reward = cl '''從機翼座標裡抽取 11 點當作 state''' x1, y1 = get_coords_plain(airfoil._spline(6)) '''state : 22 個機翼形狀值, 1 個角度, 1 個 cl, cd''' # self.state = np.append(np.append(np.append(np.append(x1, y1),angular), cl), cd) # self.state = np.append(np.append(x1, y1),angular) self.state = np.append(x1, y1) done = 1 return np.array(self.state), reward, done, {} def step1(self, action): # assert self.action_space.contains(action), "%r (%s) invalid"%(action, type(action)) angular = action[6] k = action[0:6] airfoil = construct_airfoil(*k) x, y = get_coords_plain(airfoil._spline(100)) x1, y1 = get_coords_plain(airfoil._spline(6)) self.xf.airfoil = Airfoil(x=x, y=y) # state = self.state self.xf.Re = 1e6 self.xf.M = 0.04 cl, cd, cm, cp = self.xf.a(angular) if np.isnan(cl) or np.isnan(cd) or np.isnan(cm) or np.isnan(cp): # reward = np.nan reward = -10 # self.state = self.reset() done = 0 else: # reward = cl/cd reward = cl done = 1 # self.state = np.append(np.append(np.append(np.append(x1, y1),angular), cl), cd) # self.state = np.append(np.append(x1, y1),angular) self.state = np.append(x1, y1) return np.array(self.state), reward, done, x, y def reset(self): # (.01, .4), (.05, .4), (1, 3), (0.05, 3), (0.4, 8), (1, 10) # 0.08813299, 0.28250898, 2.80168427, 2.56204214, 1.48703742, 8.53824561 '''為了避免 state 有無窮大的值, 所以設定decays範圍''' # decays = [1.0, 0.5, 0.25, 0.125, 0.0625] decays = [1.0, 0.999, 0.995, 0.99, 0.95, 0.9, 0.5] for decay in decays: tmp1 = self.np_random.uniform(low=-1.0, high=1.0, size=(7,)) # tmp = tmp * [0.39, 0.35, 2.0, 2.95, 7.6, 9, 10] + [0.01, 0.05, 1, 0.05, 0.4, 1, 0] # tmp = tmp * [0.01, 0.1, 0.5, 0.5, 0.1, 1.0, 5] + [0.08813299, 0.28250898, 2.50168427, 2.56, 1.487, 8.54, 0] # k = [0.1584, 0.1565, 2.1241, 1.8255, 3.827, 11.6983] '''從標準NACA5410開始找''' tmp1 = tmp1 * decay tmp = tmp1 * [0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 5] + [0.1584, 0.1565, 2.1241, 1.8255, 11.6983, 3.827, 6] airfoil = construct_airfoil(*tmp) x, y = get_coords_plain(airfoil._spline(100)) self.xf.airfoil = Airfoil(x=x, y=y) self.xf.Re = 1e6 self.xf.M = 0.04 cl, cd, cm, cp = self.xf.a(tmp[6]) if not np.isnan(cl): break x, y = get_coords_plain(airfoil._spline(6)) self.xf.Re = 1e6 self.xf.M = 0.04 # self.state = np.append(np.append(np.append(np.append(x, y), tmp1[6]), cl), cd) # self.state = np.append(np.append(x, y), tmp1[6]) self.state = np.append(x, y) self.steps_beyond_done = None return np.array(self.state) def render(self, mode='human'): return None def close(self): if self.viewer: self.viewer.close() self.viewer = None
if __name__ == "__main__": t0 = time.perf_counter() #TODO: CST airfoil for Xfoil cst_u = [ 0.135283, 0.088574, 0.177210, 0.080000, 0.231590, 0.189572, 0.192000] cst_l = [-0.101390, -0.007993, -0.240000, -0.129790, -0.147840, -0.000050, 0.221251] xx, yu, yl, t0, R0 = cst_foil(101, np.array(cst_u), np.array(cst_l), x=None, t=0.0954, tail=0.002) x = np.concatenate((np.flip(xx[1:]), xx[1:]), axis=0) y = np.concatenate((np.flip(yu[1:]), yl[1:]), axis=0) foil = Airfoil(x, y) #TODO: Xfoil xf = XFoil() xf.print = False xf.max_iter = 40 xf.airfoil = foil xf.xtr = [0.0, 0.0] Minf = 0.2 AoA = 8.0 Re = 1e7 fname = 'feature-xfoil.txt' xf.M = Minf xf.Re = Re cl, cd, cm, cp = xf.a(AoA) x, cp = xf.get_cp_distribution()