def calculate_flap_moment(x, y, alpha, x_hinge, deflection, unit_deflection = 'rad'): """For a given airfoil with coordinates x and y at angle of attack alpha (degrees), calculate the moment coefficient around the joint at x_hinge and deflection in radians (unit_deflection = 'rad') or degrees (unit_deflection = 'deg')""" # If x and y are not dictionaries with keys upper and lower, make them # be so if type(x) == list: x, y = af.separate_upper_lower(x, y) #Because parts of the program use keys 'u' and 'l', and other parts use #'upper' and 'lower' if 'u' in x.keys(): upper = {'x': x['u'], 'y': y['u']} lower = {'x': x['l'], 'y': y['l']} elif 'upper' in x.keys(): upper = {'x': x['upper'], 'y': y['upper']} lower = {'x': x['lower'], 'y': y['lower']} hinge = af.find_hinge(x_hinge, upper, lower) if deflection > 0: upper_static, upper_flap = af.find_flap(upper, hinge) lower_static, lower_flap = af.find_flap(lower, hinge, extra_points = 'lower') elif deflection < 0: upper_static, upper_flap = af.find_flap(upper, hinge, extra_points = 'upper') lower_static, lower_flap = af.find_flap(lower, hinge) else: upper_static, upper_flap = af.find_flap(upper, hinge, extra_points = None) lower_static, lower_flap = af.find_flap(lower, hinge, extra_points = None) upper_rotated, lower_rotated = af.rotate(upper_flap, lower_flap, hinge, deflection, unit_theta = unit_deflection) flapped_airfoil, i_separator = af.clean(upper_static, upper_rotated, lower_static, lower_rotated, hinge, deflection, N = None, return_flap_i = True) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #Third step: get new values of pressure coefficient xf.create_input(x = flapped_airfoil['x'], y_u = flapped_airfoil['y'], filename = 'flapped', different_x_upper_lower = True) Data = xf.find_pressure_coefficients('flapped', alpha, NACA = False) x, y, Cp = af.separate_upper_lower(x = Data['x'], y = Data['y'], Cp = Data['Cp'], i_separator = i_separator) #At the hinges, the reaction moment has the opposite sign of the #actuated torque Cm = - ar.calculate_moment_coefficient(x, y, Cp, alpha = alpha, c = 1., x_ref = x_hinge, y_ref = 0., flap = True) return Cm
'''Example comparing moment coefficient from xfoil relative to an in-house code. The in-house code allows for moment calculation around regions of aifoils (e.g. flap)''' import matplotlib.pyplot as plt import numpy as np import aeropy.aero_module as ar import aeropy.xfoil_module as xf # For a single angle of attack alpha = 0. data = xf.find_pressure_coefficients('naca0012', alpha) C_m = ar.calculate_moment_coefficient(data['x'], data['y'], data['Cp'], alpha) data_CM = xf.find_coefficients('naca0012', alpha, delete=True) print('calculated:', C_m) print('objective:', data_CM['CM']) # FOr multiple angles of attack Cm_xfoil = [] Cm_aeropy = [] alpha_list = np.linspace(0, 10, 11) for alpha in alpha_list: alpha = float(alpha) data = xf.find_pressure_coefficients('naca0012', alpha, delete=True) Cm_aeropy.append(ar.calculate_moment_coefficient(data['x'], data['y'], data['Cp'], alpha)) data_CM = xf.find_coefficients('naca0012', alpha, delete=True)
def calcairfoil(self, stage, blade: str, station: str, plot_airfoil=False, plot_ploar=False, plot_cp=False, plot_sv=False): """Calculate Bezier-PARSEC variables and airfoil properties.""" avle, avte, rvle, rvte, v1, v2, radius = ut.get_vars(stage=stage, blade=blade, station=station) cx = v1 * m.cos(r(avle)) u = stage.rpm / 60 * 2 * m.pi * radius betam = d(m.atan((m.tan(r(avle)) + m.tan(r(avte))) / 2)) self.dh = v2 / v1 self.space = (2 * m.pi * radius) / self.z # self.chord = stage.span/self.ar # self.sigma = self.chord/self.space # self.df = ((1 - m.cos(r(avle))/m.cos(r(avte))) # + ((m.cos(r(avle))*(m.tan(r(avle)) - m.tan(r(avte)))) # / (2*self.sigma))) self.sigma = ((m.cos(r(avle)) * (m.tan(r(avle)) - m.tan(r(avte)))) / (2 * (m.cos(r(avle)) / m.cos(r(avte)) - 1 + self.df))) self.chord = self.sigma * self.space # Incidence, deviation, and blade angle calculation self.deflection = abs(avle - avte) self.incidence, _n_slope = ut.calcincidence(thickness=2 * self.yt, solidity=self.sigma, relative_inlet_angle=rvle) self.deviation, _m_slope = ut.calcdeviation(thickness=2 * self.yt, solidity=self.sigma, relative_inlet_angle=rvle) self.blade_angle_i = avle - self.incidence self.blade_angle_e = avte - self.deviation self.camber = abs(self.blade_angle_i - self.blade_angle_e) # Compare to: # self.camber2 = (self.deflection # - (self.incidence # - self.deviation))/(1 - m_slope + n_slope) # self.blade_angle_e2 = self.blade_angle_i + self.camber2 # Assumes double circular arc airfoil to estimate stagger self.stagger = (self.blade_angle_i * self.xcr + self.blade_angle_e * (1 - self.xcr)) self.aoa = abs(self.stagger - avle) # Redefine blade angles to sw blade angles (stagger independent) self.cle = self.blade_angle_i - self.stagger self.cte = self.stagger - self.blade_angle_e # Assume NACA 4 definition of wedge angle and leading edge radius self.rle = 1.1019 * (2 * self.yt)**2 self.wte = 2 * d(m.atan(1.16925 * (2 * self.yt))) # TE radius done in sw # Calculate natural xc,yc from cle and cte using ycr altitutde ratio self.xc = m.tan(r( self.cte)) / (m.tan(r(self.cle)) + m.tan(r(self.cte))) # self.ycr = (self.xc + 1)/2 self.yc = self.ycr * self.xc * abs(m.tan(r(self.cle))) # Assume NACA 4 curvature self.kc, self.kt = ut.curvatures(xc=self.xc, yc=self.yc, xt=self.xt, yt=self.yt) self.bc, self.bt = ut.beziers(xc=self.xc, yc=self.yc, kc=self.kc, xt=self.xt, yt=self.yt, kt=self.kt, cle=self.cle, cte=self.cte, rle=self.rle, blade=blade, station=station) airfoil_name = blade + '_' + station wf.create_coord_file(filename=airfoil_name, plot=plot_airfoil, xc=self.xc, yc=self.yc, kc=self.kc, bc=self.bc, xt=self.xt, yt=self.yt, kt=self.kt, bt=self.bt, cle=self.cle, cte=self.cte, wte=self.wte, rle=self.rle) self.Re = self.rho * v1 * self.chord / self.mu self.polar = xf.find_coefficients(airfoil=airfoil_name, indir='Input', outdir='Output', alpha=self.aoa, Reynolds=self.Re, iteration=500, echo=False, delete=False, NACA=False, PANE=True) self.cp = xf.find_pressure_coefficients(airfoil=airfoil_name, alpha=self.aoa, indir='Input', outdir='Output', Reynolds=self.Re, iteration=500, echo=False, NACA=False, chord=1., PANE=True, delete=False) self.sv = {'x': list(), 'y': list(), 'v': list()} for i in range(len(self.cp['Cp'])): self.sv['x'].append(self.cp['x'][i]) # self.sv['y'].append(self.cp['y'][i]) self.sv['v'].append(m.sqrt(1 - self.cp['Cp'][i])) if plot_cp: plt.plot(self.cp['x'], self.cp['Cp']) plt.show() if plot_sv: plt.plot(self.sv['x'], self.sv['v']) plt.show() if plot_ploar: # Gather multiple angles of attack for airfoil and get polars alphas = list(range(-30, 30)) polars = xf.find_coefficients(airfoil=airfoil_name, alpha=alphas, Reynolds=self.Re, iteration=500, delete=True, echo=False, NACA=False, PANE=True) # Plot airfoil plt.plot(polars['alpha'], polars['CL']) plt.show() try: cl = self.polar['CL'] cd = self.polar['CD'] gamma = m.atan(cd / cl) self._psi = (((cx / u) / 2) * ut.sec(r(betam)) * self.sigma * (cl + cd * m.tan(r(betam)))) self.psi_opt = (((cx / u) / m.sqrt(2)) * self.sigma * (cl + cd)) self.dX = ((self.rho * cx**2 * self.chord * cl / (2 * m.cos(r(betam))**2)) * m.sin(r(betam) - gamma) / m.cos(gamma)) self.dTau = ( (self.rho * cx**2 * self.chord * cl * self.z * radius / (2 * m.cos(r(betam))**2)) * m.cos(r(betam) - gamma) / m.cos(gamma)) self.delta_p = cl * ((self.rho * cx**2 * self.chord / (2 * self.space * m.cos(r(betam))**2)) * m.sin(r(betam) - gamma) / m.cos(gamma)) self.delta_T = (cl / 1.005) * ( (u * cx * self.chord / (2 * self.space * m.cos(r(betam))**2)) * m.cos(r(betam) - gamma) / m.cos(gamma)) self.efficiency = (cx/u)*m.tan(r(betam) - gamma)\ + cx*m.tan(r(rvte))/(2*u) except TypeError: print('Design point did not converge in xfoil.') # pass print(f'{station} {blade} Performance') print(f' DF: {self.df:.2f} (<=0.6)') print(f' DH: {self.dh:.2f} (>=0.72)') print(f' i : {self.incidence:.2f} deg') print(f' d : {self.deviation:.2f} deg') print('\n')