def shape_difference(inputs, optimize_deltaz=False): if optimize_deltaz == True or optimize_deltaz == [True]: y_u = CST(upper['x'], 1, deltasz=inputs[-1] / 2., Au=list(inputs[:n + 1])) y_l = CST(lower['x'], 1, deltasz=inputs[-1] / 2., Al=list(inputs[n + 1:-1])) else: y_u = CST(upper['x'], 1, deltasz=deltaz / 2., Au=list(inputs[:n + 1])) y_l = CST(lower['x'], 1, deltasz=deltaz / 2., Al=list(inputs[n + 1:])) # Vector to be compared with a_u = {'x': upper['x'], 'y': y_u} a_l = {'x': lower['x'], 'y': y_l} b_u = upper b_l = lower return hausdorff_distance_2D(a_u, b_u) + hausdorff_distance_2D( a_l, b_l)
def calculate_spar_distance(psi_baseline, Au_baseline, Au_goal, Al_goal, deltaz, c_goal): """Calculate spar distance (dimensional)""" def f(psi_lower_goal): y_lower_goal = CST(psi_lower_goal * c_goal, c_goal, [deltaz / 2., deltaz / 2.], Au_goal, Al_goal) y_lower_goal = y_lower_goal['l'] return psi_upper_goal + (s[0] / s[1]) * (y_lower_goal - y_upper_goal) / c_goal # Calculate cruise chord c_baseline = calculate_c_baseline(c_goal, Au_baseline, Au_goal, deltaz) # Calculate upper psi at goal airfoil psi_upper_goal = calculate_psi_goal(psi_baseline, Au_baseline, Au_goal, deltaz, c_baseline, c_goal) y_upper_goal = CST(psi_upper_goal * c_goal, c_goal, [deltaz / 2., deltaz / 2.], Au_goal, Al_goal) y_upper_goal = y_upper_goal['u'] # Spar direction s = calculate_spar_direction(psi_baseline, Au_baseline, Au_goal, deltaz, c_goal) # Calculate lower psi and xi at goal airfoil # Because the iterative method can lead to warningdivision by zero after # converging, we ignore the warning np.seterr(divide='ignore', invalid='ignore') psi_lower_goal = optimize.fixed_point(f, [psi_upper_goal]) x_lower_goal = psi_lower_goal * c_goal y_lower_goal = CST(x_lower_goal, c_goal, [deltaz / 2., deltaz / 2.], Au_goal, Al_goal) y_lower_goal = y_lower_goal['l'] return (y_upper_goal - y_lower_goal[0]) / s[1]
def shape_difference(inputs, optimize_deltaz=False, surface=surface): # Define deltaz if optimize_deltaz is True or optimize_deltaz == [True]: deltasz = inputs[-1] / 2. else: deltasz = deltaz / 2. # Calculate upper and lower surface if surface == 'both': y_u = CST(upper['x'], 1, deltasz=deltasz, Au=list(inputs[:n + 1])) y_l = CST(lower['x'], 1, deltasz=deltasz, Al=list(inputs[n + 1:-1])) elif surface == 'upper': y_u = CST(upper['x'], 1, deltasz=deltasz, Au=list(inputs[:n + 1])) elif surface == 'lower': y_l = CST(lower['x'], 1, deltasz=deltasz, Al=list(inputs[:n + 1])) # Vector to be compared with error = 0 if surface == 'upper' or surface == 'both': a_u = {'x': upper['x'], 'y': y_u} if objective == 'hausdorf': error += hausdorff_distance_2D(a_u, upper) elif objective == 'squared_mean': error += np.mean( (np.array(a_u['x']) - np.array(upper['x']))**2 + (np.array(a_u['y']) - np.array(upper['y']))**2) if surface == 'lower' or surface == 'both': a_l = {'x': lower['x'], 'y': y_l} if objective == 'hausdorf': error += hausdorff_distance_2D(a_l, lower) elif objective == 'squared_mean': error += np.mean( (np.array(a_l['x']) - np.array(lower['x']))**2 + (np.array(a_l['y']) - np.array(lower['y']))**2) # plt.figure() # plt.scatter(a_u['x'], a_u['y'], c='k') # plt.scatter(a_l['x'], a_l['y'], c='b') # plt.scatter(upper['x'], upper['y'], c='r') # plt.scatter(lower['x'], lower['y'], c='g') # plt.show() return error
def coefficient_LLT(AC, velocity, AOA): Au_P = [0.1828, 0.1179, 0.2079, 0.0850, 0.1874] Al_P = Au_P deltaz = 0 # Determine children shape coeffcients AC_u = list(data.values[i, 0:4]) Au_C, Al_C, c_C, spar_thicknesses = calculate_dependent_shape_coefficients( AC_u, psi_spars, Au_P, Al_P, deltaz, c_P, morphing=morphing_direction) # Calculate aerodynamics for that airfoil airfoil = 'optimal' x = create_x(1., distribution='linear') y = CST(x, 1., [deltaz / 2., deltaz / 2.], Al=Al_C, Au=Au_C) # Create file for Xfoil to read coordinates xf.create_input(x, y['u'], y['l'], airfoil, different_x_upper_lower=False) Data = xf.find_coefficients(airfoil, AOA, Reynolds=Reynolds(10000, velocity, c_C), iteration=100, NACA=False) deviation = 0.001 while Data['CL'] is None: Data_aft = xf.find_coefficients(airfoil, AOA * deviation, Reynolds=Reynolds( 10000, velocity, c_C), iteration=100, NACA=False) Data_fwd = xf.find_coefficients(airfoil, AOA * (1 - deviation), Reynolds=Reynolds( 10000, velocity, c_C), iteration=100, NACA=False) try: for key in Data: Data[key] = (Data_aft[key] + Data_fwd[key]) / 2. except: deviation += deviation alpha_L_0 = xf.find_alpha_L_0(airfoil, Reynolds=0, iteration=100, NACA=False) coefficients = LLT_calculator(alpha_L_0, Data['CD'], N=100, b=span, taper=1., chord_root=chord_root, alpha_root=AOA, V=velocity) lift = coefficients['C_L'] drag = coefficients['C_D'] return lift, drag
def dxi_u(psi, Au, delta_xi, N1=0.5, N2=1): """Calculate upper derivate of xi for a given psi""" n = len(Au) - 1 xi_0 = CST(psi, 1, 0, Au, N1=N1, N2=N2) diff = xi_0 * ((1 - n - N2)) for i in range(n + 1): # print N1-1., N2-1. # print psi**(N1-1.), (1-psi)**(N2-1.) # print Au[i]*K(i,n)*(psi**i)*((1-psi)**(n-i))*(i+N1-psi*(n+N1+N2)) diff += (psi**(N1-1))*((1-psi)**(N2-1)) * \ Au[i]*K(i, n)*(psi**i)*((1-psi)**(n-i))*(i+N1-psi*(n+N1+N2)) return diff
def _x3_CST(self, x1, diff=None): N1 = 1. N2 = 1. A0 = self.tip_displacement / max(x1) A = [A0] + list(self.D) if diff is None: return (CST(x1, max(x1), deltasz=self.tip_displacement, Au=A, N1=N1, N2=N2)) elif diff == 'x1': psi = x1 / max(x1) return (dxi_u(psi, A, delta_xi, N1=N1, N2=N2)) elif diff == 'x11': return (ddxi_u(psi, A, N1=N1, N2=N2)) elif diff == 'theta3': return (np.zeros(len(x1)))
# tracing : A = calculate_shape_coefficients_tracing(AC_u0, ValX, ValY, 0.5, 1., c_C, deltaz) # structurally_consistent : Au_C, Al_C, c_C, spar_thicknesses = calculate_dependent_shape_coefficients( A[1:], psi_spars, Au_P, Al_P, deltaz, c_P, morphing=morphing_direction) error = abs((AC_u0 - Au_C[0]) / AC_u0) print('Iteration: ' + str(counter) + ', Error: ' + str(error)) AC_u0 = Au_C[0] counter += 1 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Plotting : #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ x = np.linspace(0, c_C, 1000) y = CST(x, c_C, deltasz=[deltaz / 2., deltaz / 2.], Al=Al_C, Au=Au_C) plt.plot(x, y['u'], 'b', label='Children', lw=2) plt.plot(x, y['l'], 'b', label=None, lw=2) # Print shape for parent x = np.linspace(0, c_P, 1000) y = CST(x, c_P, deltasz=[deltaz / 2., deltaz / 2.], Al=Al_P, Au=Au_P) plt.plot(x, y['u'], 'r--', label='Parent', lw=2) plt.plot(x, y['l'], 'r--', label=None, lw=2) if morphing_direction == 'forwards': psi_flats = [] intersections_x_children = [0] intersections_y_children = [0] intersections_x_parent = [0] intersections_y_parent = [0]
def calculate_camber(psi, Au, Al, delta_xi): xi = CST(psi, 1., [delta_xi/2., delta_xi/2.], Au, Al) return (xi['u']+xi['l'])/2.
def calculate_average_camber(Au, Al, delta_xi): psi = np.linspace(0, 1, 1000) xi = CST(psi, 1., [delta_xi/2., delta_xi/2.], Au, Al) camber = (xi['u']+xi['l'])/2. return np.average(np.absolute(camber))
def aerodynamic_performance(AC, psi_spars, Au_P, Al_P, c_P, deltaz, alpha, H, V): morphing_direction = 'forwards' air_data = air_properties(H, unit='feet') density = air_data['Density'] dyn_pressure = .5 * density * V**2 # Generate dependent shape coefficients # try: Au_C, Al_C, c_C, spar_thicknesses = calculate_dependent_shape_coefficients( AC, psi_spars, Au_P, Al_P, deltaz, c_P, morphing=morphing_direction) # print 'Reynolds: ', Reynolds(H, V, c_C) # Generate aifoil file airfoil = 'test' x = create_x(1., distribution='linear', n=300) y = CST(x, 1., [deltaz / 2., deltaz / 2.], Au=Au_C, Al=Al_C) # Get strain data strains, av_strain = calculate_strains(Au_P, Al_P, c_P, Au_C, Al_C, c_C, deltaz, psi_spars, spar_thicknesses) intersections = intersect_curves(x, y['l'], x, y['u']) print(intersections, intersections[0][1:]) if len(intersections[0][1:]) == 0: # print y create_input(x, y['u'], y['l'], airfoil, different_x_upper_lower=False) # Get aerodynamic data print(airfoil, alpha, Reynolds(H, V, c_C)) Data = find_coefficients(airfoil, alpha, Reynolds=Reynolds(H, V, c_C), iteration=200, NACA=False, delete=True, PANE=True, GDES=True) # plot_airfoil(AC, psi_spars, c_P, deltaz, Au_P, Al_P, image = 'save', iteration=counter, dir = airfoil+'_dir') # filtering data (for now I only care about negative strains str_output = { 'CL': Data['CL'], 'CD': Data['CD'], 'CM': Data['CM'], 'av_strain': av_strain, 'Au_C': Au_C, 'Al_C': Al_C, 'spars': psi_spars } if Data['CM'] == None: str_output['lift'] = None str_output['drag'] = None str_output['moment'] = None else: str_output['lift'] = Data['CL'] / dyn_pressure / c_C, str_output['drag'] = Data['CD'] / dyn_pressure / c_C, str_output['moment'] = Data['CM'] / dyn_pressure / c_C for i in range(len(strains)): str_output['strain_' + str(i)] = strains[i] # Writing to a text file # f_worker = open(str(airfoil) + '.txt', 'wb') # for i in range(len(key_list)): # if i != len(key_list)-1: # if key_list[i][:1] == 'Au': # f_worker.write('%f\t' % str_output[key_list[i][:1]+'_C'][int(key_list[i][-1])]) # else: # else: # if key_list[i][:1] == 'Au': # f_worker.write('%f\n' % str_output[key_list[i][:1]+'_C'][int(key_list[i][-1])]) else: str_output = { 'CL': 1000, 'CD': None, 'CM': None, 'av_strain': av_strain, 'spars': psi_spars, 'Au_C': Au_C, 'Al_C': Al_C, 'lift': None, 'drag': None, 'moment': None } for i in range(len(strains)): str_output['strain_' + str(i)] = strains[i] # except: # str_output = {'CL':None, 'CD':None, 'CM':None, 'av_strain':None, # 'Au_C':[None]*len(AC), 'Al_C': [None]*len(AC), # 'lift': None, 'drag': None, 'moment':None, # 'strains':[None]*(len(AC)-1), 'spars':psi_spars} return str_output
def f(psi_lower_goal): y_lower_goal = CST(psi_lower_goal*c_goal, c_goal, [deltaz/2., deltaz/2.], Au_goal, Al_goal) y_lower_goal = y_lower_goal['l'] return psi_upper_goal + (s[0]/s[1])*(y_lower_goal - y_upper_goal)/c_goal
import matplotlib.pyplot as plt #testing = 'structurally_consistent' testing = 'tracing' if testing == 'tracing': N1 = 1. N2 = 1. tip_displacement = {'x': .1, 'y':1.} other_points = {'x': [0.01, -0.03, .05, 0.12], 'y':[0.1, 0.3, .5, 0.8]} A0 = -tip_displacement['x'] print(A0) A = calculate_shape_coefficients_tracing(A0, tip_displacement, other_points, N1, N2) #plotting y = np.linspace(0, tip_displacement['y'], 100000) x = CST(y, tip_displacement['y'], deltasz= tip_displacement['x'], Au = A, N1=N1, N2=N2) plt.plot(x,y) plt.scatter(other_points['x'] + [tip_displacement['x']], other_points['y'] + [tip_displacement['y']]) plt.gca().set_aspect('equal', adjustable='box') plt.show() elif testing == 'structurally_consistent': #============================================================================== # Inputs #============================================================================== # Parameter c_P = 1. #m deltaz = 0.*c_P #m
AOAs = AOAs[0] velocities = velocities[0] # data = {'Names':airfoil_database['names'], 'AOA':AOAs, 'V':velocities, # 'L/D':[], 'Expected':[]} f = open('aerodynamics_3.p', 'rb') data = pickle.load(f) f.close() for j in range(1145, len(Au_database)): data['L/D'].append([]) print(j, airfoil_database['names'][j]) Au = Au_database[j, :] Al = Al_database[j, :] x = create_x(1., distribution = 'linear') y = CST(x, chord, deltasz=[du_database[j], dl_database[j]], Al=Al, Au=Au) xf.create_input(x, y['u'], y['l'], airfoil, different_x_upper_lower = False) for i in range(len(AOAs)): AOA = AOAs[i] V = velocities[i] try: Data = xf.find_coefficients(airfoil, AOA, Reynolds=Reynolds(10000, V, chord), iteration=100, NACA=False, delete=True) lift_drag_ratio = Data['CL']/Data['CD'] except: lift_drag_ratio = None increment = 0.1 conv_counter = 0
def generate_geometries_animate(length_0, A, TE_displacement, N1, N2, thickness, x_to_track=[]): # new chord current_chord = calculate_c(length_0, A, TE_displacement, N1, N2) # Get coordinates for specific points in the neutral line tracked = {'x': [], 'y': []} for x in x_to_track: tracked['y'].append(current_chord * calculate_deformed_psi( x / length_0, length_0, current_chord, A, TE_displacement)[0]) tracked['x'] = CST(tracked['y'], current_chord, TE_displacement, Au=A, N1=N1, N2=N2) # Get offset values for left side left_tracked = {'x': [], 'y': []} for i in range(len(x_to_track)): dxi = dxi_u(tracked['y'][i] / current_chord, A, TE_displacement / current_chord) xi_component = -dxi / (dxi**2 + 1)**.5 psi_component = 1 / (dxi**2 + 1)**.5 left_tracked['x'].append(tracked['x'][i] - thickness / 2 * psi_component) left_tracked['y'].append(tracked['y'][i] - thickness / 2 * xi_component) # Get offset values for right side right_tracked = {'x': [], 'y': []} for i in range(len(x_to_track)): dxi = dxi_u(tracked['y'][i] / current_chord, A, TE_displacement / current_chord) xi_component = -dxi / (dxi**2 + 1)**.5 psi_component = 1 / (dxi**2 + 1)**.5 right_tracked['x'].append(tracked['x'][i] + thickness / 2 * psi_component) right_tracked['y'].append(tracked['y'][i] + thickness / 2 * xi_component) # non-dimensional y coordinates (extend it a little on the bottom to guarantee nice shape) psi = np.linspace(-.1, current_chord, 1000) # non-dimensional x coordinates xi = CST(psi, current_chord, TE_displacement, Au=A, N1=N1, N2=N2) # Genrate neutral line line = LineString(zip(xi, psi)) # Create offsets to neutral line offset_left = line.parallel_offset(thickness / 2., 'left', join_style=1) offset_right = line.parallel_offset(thickness / 2., 'right', join_style=1) # Create baffle coords = (offset_left.coords[:] + offset_right.coords[::] + [offset_left.coords[0]]) main = Polygon(coords) # Remove base material coords = ((-1, 0), (-1, -1), (1, -1), (1, 0), (-1, 0)) root = Polygon(coords) main = main.difference(root) # 3Plot tracked points # plt.scatter(right_tracked['x'],right_tracked['y'],c='c') # plt.scatter(left_tracked['x'],left_tracked['y'],c='g') # plt.scatter([0]*len(x_to_track),x_to_track, c='b') # plt.scatter(tracked['x'],tracked['y'], c='r') # Plot geometry skin_patch = PolygonPatch(main, facecolor='#909090', edgecolor='#909090', alpha=0.5, zorder=2) return skin_patch
def plot_airfoil(AC, psi_spars, c_P, deltaz, Au_P, Al_P, image='plot', iteration=0, return_coordinates=True, dir='current', morphing_direction='backwards'): import matplotlib.pyplot as plt # plt.figure() n = len(Au_P) - 1 Au_C, Al_C, c_C, spar_thicknesses = calculate_dependent_shape_coefficients( AC, psi_spars, Au_P, Al_P, deltaz, c_P, morphing=morphing_direction) print('CST chord', c_C) # ============================================================================== # Plot results # ============================================================================== np.set_printoptions(precision=20) x = np.linspace(0, c_C, 1000) y = CST(x, c_C, deltasz=[deltaz / 2., deltaz / 2.], Al=Al_C, Au=Au_C) plt.plot(x, y['u'], 'b', label='Children', lw=1) plt.plot(x, y['l'], '-b', label=None, lw=1) # store variables in case return_coordinates is True x = list(x[::-1]) + list(x[1:]) y = list(y['u'][::-1]) + list(y['l'][1:]) children_coordinates = {'x': x, 'y': y} x = np.linspace(0, c_P, 1000) y = CST(x, c_P, deltasz=[deltaz / 2., deltaz / 2.], Al=Al_P, Au=Au_P) plt.plot(x, y['u'], 'r--', label='Parent', lw=1) plt.plot(x, y['l'], 'r--', label=None, lw=1) y_limits = y if morphing_direction == 'backwards': for i in range(len(psi_spars)): psi_i = psi_spars[i] # Calculate psi at landing psi_goal_i = calculate_psi_goal(psi_i, Au_C, Au_P, deltaz, c_C, c_P) x_goal_i = psi_goal_i * c_P # Calculate xi at landing temp = CST(x_goal_i, c_P, [deltaz / 2., deltaz / 2.], Al=Al_P, Au=Au_P) y_goal_i = temp['u'] # calculate spar direction s = calculate_spar_direction(psi_i, Au_C, Au_P, deltaz, c_P) plt.plot([x_goal_i, x_goal_i - spar_thicknesses[i] * s[0]], [y_goal_i, y_goal_i - spar_thicknesses[i] * s[1]], 'r--') y = CST(np.array([psi_i * c_C]), c_C, deltasz=[deltaz / 2., deltaz / 2.], Al=Al_C, Au=Au_C) plt.plot([psi_i * c_C, psi_i * c_C], [y['u'], y['u'] - spar_thicknesses[i]], 'b', label=None) elif morphing_direction == 'forwards': for j in range(len(psi_spars)): psi_parent_j = psi_spars[j] # Calculate psi at landing # psi_baseline, Au_baseline, Au_goal, deltaz, c_baseline, c_goal psi_children_j = calculate_psi_goal(psi_parent_j, Au_P, Au_C, deltaz, c_P, c_C) x_children_j = psi_children_j * c_C # Calculate xi at landing temp = CST(x_children_j, c_C, [deltaz / 2., deltaz / 2.], Al=Al_C, Au=Au_C) y_children_j = temp['u'] s = calculate_spar_direction(psi_spars[j], Au_P, Au_C, deltaz, c_C) # Print spars for children if not inverted: plt.plot( [x_children_j, x_children_j - spar_thicknesses[j] * s[0]], [y_children_j, y_children_j - spar_thicknesses[j] * s[1]], c='b', lw=1, label=None) else: plt.plot([ x_children_j, x_children_j - spar_thicknesses[j] * s[0] ], [-y_children_j, -y_children_j + spar_thicknesses[j] * s[1]], c='b', lw=1, label=None) y = CST(np.array([psi_parent_j * c_P]), c_P, deltasz=[deltaz / 2., deltaz / 2.], Al=Al_P, Au=Au_P) # Print spars for parents if not inverted: plt.plot([psi_parent_j * c_P, psi_parent_j * c_P], [y['u'], y['u'] - spar_thicknesses[j]], 'r--', lw=1, label=None) else: plt.plot([psi_parent_j * c_P, psi_parent_j * c_P], [-y['u'], -y['u'] + spar_thicknesses[j]], 'r--', lw=1, label=None) plt.plot([psi_i * c_C, psi_i * c_C], [y['u'], y['u'] - spar_thicknesses[i]], 'b', label=None) plt.xlabel('$\psi$', fontsize=16) plt.ylabel(r'$\xi$', fontsize=16) plt.grid() plt.legend(loc="upper right") plt.gca().set_aspect(2, adjustable='box') x1, x2, y1, y2 = plt.axis() plt.axis((x1, x2, y1, 2 * y2)) # plt.axis([-0.005, c_L+0.005, min(y_limits['l'])-0.005, max(y_limits['l'])+0.01]) if image == 'plot': plt.show() elif image == 'save': if dir == 'current': plt.savefig('%03i.pdf' % (iteration), bbox_inches='tight') else: cwd = os.getcwd() directory = os.path.join(cwd, dir) if not os.path.exists(directory): os.makedirs(directory) filename = os.path.join(directory, '%05i.png' % (iteration)) plt.savefig(filename, bbox_inches='tight') if return_coordinates: return children_coordinates
def generate_geometries(length_0, A, TE_displacement, N1, N2, thickness, x_to_track=[]): # new chord current_chord = calculate_c(length_0, A, TE_displacement, N1, N2) # Get coordinates for specific points in the neutral line tracked = {'x': [], 'y': []} for x in x_to_track: tracked['y'].append(current_chord * calculate_deformed_psi( x / length_0, length_0, current_chord, A, TE_displacement)[0]) tracked['x'] = CST(tracked['y'], current_chord, TE_displacement, Au=A, N1=N1, N2=N2) # Get offset values for left side left_tracked = {'x': [], 'y': []} for i in range(len(x_to_track)): dxi = dxi_u(tracked['y'][i] / current_chord, A, TE_displacement / current_chord, N1, N2) xi_component = -dxi / (dxi**2 + 1)**.5 psi_component = 1 / (dxi**2 + 1)**.5 left_tracked['x'].append(tracked['x'][i] - thickness / 2 * psi_component) left_tracked['y'].append(tracked['y'][i] - thickness / 2 * xi_component) # Get offset values for right side right_tracked = {'x': [], 'y': []} for i in range(len(x_to_track)): dxi = dxi_u(tracked['y'][i] / current_chord, A, TE_displacement / current_chord, N1, N2) xi_component = -dxi / (dxi**2 + 1)**.5 psi_component = 1 / (dxi**2 + 1)**.5 right_tracked['x'].append(tracked['x'][i] + thickness / 2 * psi_component) right_tracked['y'].append(tracked['y'][i] + thickness / 2 * xi_component) # non-dimensional y coordinates (extend it a little on the bottom to guarantee nice shape) psi = np.linspace(-.1, current_chord, 1000) # non-dimensional x coordinates xi = CST(psi, current_chord, TE_displacement, Au=A, N1=N1, N2=N2) fig = plt.figure(1, figsize=SIZE, dpi=90) ax = fig.add_subplot(111) ax.set_aspect('equal') # Genrate neutral line line = LineString(zip(xi, psi)) # Create offsets to neutral line offset_left = line.parallel_offset(thickness / 2., 'left', join_style=1) offset_right = line.parallel_offset(thickness / 2., 'right', join_style=1) # Create baffle coords = (offset_left.coords[:] + offset_right.coords[::] + [offset_left.coords[0]]) main = Polygon(coords) # Remove base material coords = ((-1, 0), (-1, -1), (1, -1), (1, 0), (-1, 0)) root = Polygon(coords) main = main.difference(root) # Plot tracked points plt.scatter(right_tracked['x'], right_tracked['y'], c='c') plt.scatter(left_tracked['x'], left_tracked['y'], c='g') plt.scatter([0] * len(x_to_track), x_to_track, c='b') plt.scatter(tracked['x'], tracked['y'], c='r') # Plot geometry skin_patch = PolygonPatch(main, facecolor='#808080', edgecolor='#808080', alpha=0.5, zorder=2) ax.add_patch(skin_patch) plt.xlabel('x', fontsize=14) plt.ylabel('y', fontsize=14) plt.grid() plt.show() # Get the flag flags = [] x, y = find_point_inside(main) flags.append((x, y)) # Export data data_main = extract_poly_coords(main) data = { 'model': data_main, 'flags': flags, 'left': left_tracked, 'right': right_tracked } output_file = 'curves.p' fileObject = open(output_file, 'wb') pickle.dump(data, fileObject) fileObject.close()
length_0 = 1. # Delta x TE_displacement = 0.1 # Shape coefficients A = [-TE_displacement, 0.2] # new chord current_chord = calculate_c(length_0, A, TE_displacement, N1, N2) #current_chord = 1 # non-dimensional y coordinates y = np.linspace(0, current_chord) # non-dimensional x coordinates x = CST(y, current_chord, TE_displacement, Au=A, N1=N1, N2=N2) dxi = dxi_u(psi=np.array(y) / current_chord, Au=A, delta_xi=TE_displacement / current_chord, N1=N1, N2=N2) # Plotting plt.plot(x, y, label='A = ' + str(A[0])) plt.plot(dxi, y, label='dxi') plt.axis('equal') plt.legend() plt.grid() plt.xlabel(r'$x$', fontsize=14.) plt.ylabel('$y$', fontsize=14.)
Au_C[0] = x_i c_i = calculate_c_baseline(c_L, Au_C, Au_L, deltaz) c.append(c_i) plt.plot(x, c) plt.xlabel('$A_{u_0}^C$', fontsize=14) plt.ylabel('$c^C$', fontsize=14) plt.grid() plt.show() # Plot airfoils for different Au plt.figure() psi = np.linspace(0, 1, 500) i = 0 for c_i in c: Au_C[0] = x[i] y = CST(psi, 1, [deltaz / 2., deltaz / 2.], Au_C, Al_C) x_plot = np.linspace(0, c_i, 500) plt.plot(x_plot, c_i * y['u'], label='$A_{u_0}$ = %.1f' % x[i]) y_psi = CST(psi_i, 1, [deltaz / 2., deltaz / 2.], Au_C, Al_C) i += 1 plt.xlabel(r'$\psi^C$', fontsize=14) plt.ylabel(r'$\xi^C$', fontsize=14) plt.legend() plt.gca().set_aspect('equal', adjustable='box') plt.grid() plt.show() # Plot for several testing calculat_psi_goal plt.figure() x = np.linspace(0., 1., 6) psi_goal_list = []
import numpy as np import matplotlib.pyplot as plt import aeropy.xfoil_module as xf from aeropy.CST.module_2D import * from aeropy.aero_module import Reynolds from aeropy.geometry.airfoil import CST, create_x # Au = [0.23993240191629417, 0.34468227138908186, 0.18125405377549103, # 0.35371349126072665, 0.2440815012119143, 0.25724974995738387] # Al = [0.18889012559339036, -0.24686758992053115, 0.077569769493868401, # -0.547827192265256, -0.0047342206759065641, -0.23994805474814629] Au = [0.172802, 0.167353, 0.130747, 0.172053, 0.112797, 0.168891] Al = Au # c_avian = 0.36 #m # deltaz = 0.0093943568219451313*c_avian c_avian = 1. deltaz = 0 airfoil = 'avian' x = create_x(1., distribution='linear') y = CST(x, 1., [deltaz / 2., deltaz / 2.], Au=Au, Al=Al) # Create file for Xfoil to read coordinates xf.create_input(x, y['u'], y['l'], airfoil, different_x_upper_lower=False) print('Reynolds: ', Reynolds(10000, 30, c_avian)) Data = xf.find_coefficients(airfoil, 0., Reynolds=Reynolds(10000, 30, c_avian), iteration=100, NACA=False) print(Data)
import matplotlib.pyplot as plt import numpy as np from aeropy.geometry.airfoil import create_x, CST plt.figure() A = [1., 2., 1.] deltaz = 0.2 x = create_x(1, distribution='polar') for i in range(len(A)): A_i = [0, 0, 0] A_i[i] = A[i] y = CST(x, 1., deltaz, A_i) plt.plot(x, y, '--') y = CST(x, 1., deltaz, A) plt.plot(x, y, 'k') plt.axis('equal') plt.grid() plt.xlim([0, 1]) plt.xlabel('$\psi$', fontsize=14) plt.ylabel(r'$\xi$', fontsize=14) plt.show() plt.figure() A = [1.] N1 = [.5, 1., .5] N2 = [1., 1., .5] deltaz = 0.0 x = create_x(1, distribution='polar') for i in range(len(N1)): N1_i = N1[i]
def calculate_dependent_shape_coefficients(BP_p, BA_p, BP_c, chord_p, sweep_p, twist_p, delta_TE_p, sweep_c, twist_c, eta_sampling, psi_spars, morphing='camber'): """Calculate dependent shape coefficients for children configuration for a 4 order Bernstein polynomial and return the children upper, lower shape coefficients, children chord and spar thicknesses. _P denotes parent parameters""" def calculate_BP_c0(BP_c0, c_P, deltaz, j): Au_C = extract_A(BP_c, j) Au_P = extract_A(BP_p, j) c_C = calculate_c_baseline(c_P, Au_C, Au_P, deltaz) BP_c[0][j] = np.sqrt(c_P / c_C) * Au_P[0] return BP_c[0][j], c_C def extract_A(B, j): # Extracting shape coefficient data for column j A = [] for i in range(n + 1): A.append(B[i][j]) return A # Bersntein Polynomial def K(r, n): K = math.factorial(n) / (math.factorial(r) * math.factorial(n - r)) return K # Bernstein Polynomial orders (n is for psi, and m for eta) n = len(BP_p) - 1 m = len(BP_p[0]) - 1 p = len(psi_spars) q = len(eta_sampling) # print p,q,n,m # Define chord, sweep, and twist functions for parent chord_p = CST(eta_sampling, chord_p['eta'][1], chord_p['initial'], Au=chord_p['A'], N1=chord_p['N1'], N2=chord_p['N2'], deltasLE=chord_p['final']) sweep_p = CST(eta_sampling, sweep_p['eta'][1], deltasz=sweep_p['final'], Au=sweep_p['A'], N1=sweep_p['N1'], N2=sweep_p['N2']) chord_p = chord_p[::-1] sweep_p = sweep_p twist_p = CST(eta_sampling, twist_p['eta'][1], twist_p['initial'], Au=twist_p['A'], N1=twist_p['N1'], N2=twist_p['N2'], deltasLE=twist_p['final']) delta_TE_p = CST(eta_sampling, delta_TE_p['eta'][1], delta_TE_p['initial'], Au=delta_TE_p['A'], N1=delta_TE_p['N1'], N2=delta_TE_p['N2'], deltasLE=delta_TE_p['final']) # Initialize chord, sweep, and twist functions for child chord_c = [] # Initialize child active matrix BA_c = [] for i in range(n + 1): temp = [] for j in range(m + 1): temp.append(0) BA_c.append(temp, ) # Find upper shape coefficient though iterative method since Au_0 is # unknown via fixed point iteration for k in range(q): error = 9999 BP_c0 = BP_p[0][k] while error > 1e-9: before = BP_c0 c_P = chord_p[k] deltaz = delta_TE_p[k] [BP_c0, c_c] = calculate_BP_c0(BP_c0, c_P, deltaz, k) error = abs(BP_c0 - before) BP_c[0][k] = BP_c0 BA_c[0][k] = np.sqrt(c_P / c_c) * BA_p[0][k] chord_c.append(c_c) print(c_c, BP_c0, np.sqrt(c_P / c_c) * BA_p[0][k]) # Calculate thickness and tensor C for the constraint linear system problem psi_A_c = [] if morphing == 'camber': f = np.zeros((q, p)) for l in range(q): # Converting everything from 3D to 2D framework Au_P = extract_A(BP_p, l) Al_P = extract_A(BA_p, l) Au_C = extract_A(BP_c, l) c_P = chord_p[l] c_C = chord_c[l] deltaz = delta_TE_p[l] # psi/xi coordinates for lower surface of children configuration psi_lower_children = [] xi_upper_children = [] # psi_baseline, Au_baseline, Au_goal, deltaz, c_baseline, c_goal psi_upper_children = [] for j in range(len(psi_spars)): psi_i = calculate_psi_goal(psi_spars[j], Au_P, Au_C, deltaz, c_P, c_C) psi_upper_children.append(psi_i) # Calculate xi for upper children. Do not care about lower so just # gave it random shape coefficients xi_upper_children = CST( psi_upper_children, 1., deltasz=[deltaz / 2. / c_C, deltaz / 2. / c_C], Al=Au_C, Au=Au_C) xi_upper_children = xi_upper_children['u'] # print xi_upper_children # Debugging section # x = np.linspace(0, 1) # y = CST(x, 1., deltasz=[deltaz/2./c_C, deltaz/2./c_C], # Al=Au_C, Au=Au_C) # plt.plot(x,y['u']) # plt.scatter(psi_upper_children, xi_upper_children) # plt.grid() # plt.show() # BREAK for k in range(len(psi_spars)): xi_parent = CST(psi_spars, 1., deltasz=[deltaz / 2. / c_P, deltaz / 2. / c_P], Al=Al_P, Au=Au_P) delta_k_P = xi_parent['u'][k] - xi_parent['l'][k] # t_k = c_P*(delta_k_P) # Claculate orientation for children s_k = calculate_spar_direction(psi_spars[k], Au_P, Au_C, deltaz, c_C) psi_l_k = psi_upper_children[k] - delta_k_P / c_C * s_k[0] xi_l_k = xi_upper_children[k] - delta_k_P / c_C * s_k[1] psi_lower_children.append(psi_l_k) f_y = 0 for j in range(m + 1): f_y += BA_c[0][j]*(1-psi_l_k)**n \ * (K(j, m)*eta_sampling[l]**j * (1-eta_sampling[l])**(m-j)) f[l][k] = (2*xi_l_k + psi_l_k*deltaz/c_C) / \ (2*(psi_l_k**0.5) * (psi_l_k-1)) - f_y # print 'f_y',f_y, eta_sampling[l],m,j # Store new children psi values psi_A_c.append(psi_lower_children) # Initialize F (avoiding using numpy) F = np.zeros([q, p, m + 1, n]) # F = [] # for l in range(q): # tempk = [] # for k in range(p): # tempj = [] # for j in range(m+1): # tempi = [] # for i in range(n): # tempi.append(0.0) # tempj.append(tempi) # tempk.append(tempj) # F.append(tempk) # j is the row dimension and i the column dimension in this case for l in range(q): for k in range(p): for j in range(m + 1): for i in range(n): # Because in Python counting starts at 0, # need to add 1 to be coherent for equations ii = i + 1 Sx = K(ii, n)*(psi_A_c[l][k]**ii) * \ (1-psi_A_c[l][k])**(n-ii) Sy = K(j, m)*(eta_sampling[l]**j) * \ (1-eta_sampling[l])**(m-j) F[l][k][j][i] = Sx * Sy # print len(F), len(F[0]), len(F[0][0]), len(F[0][0][0]) # Unfolding tensor F_matrix = np.zeros((n**2, n**2)) f_vector = np.zeros((n**2, 1)) for l in range(q): for k in range(p): for j in range(m + 1): for i in range(n): ii = n * (l) + k jj = n * (j) + i F_matrix[ii][jj] = F[l][k][j][i] f_vector[ii] = f[l][k] solution = np.linalg.solve(F_matrix, f_vector) for j in range(m + 1): for i in range(n): jj = n * (j) + i BA_c[i + 1][j] = solution[jj][0] print(BA_c) return BA_c, chord_c
surface=surface, x0=None) if surface == 'both': error, fitted_deltaz, fitted_Al, fitted_Au = output print(error) print(fitted_Al) print(fitted_Au) elif surface == 'lower': error, fitted_deltaz, fitted_Al = output print('Coefficients', fitted_Al) data = output_reader(filename, separator='\t', header=['x', 'z']) plt.scatter(data['x'], data['z'], c='r') x = np.linspace(0, 1, 100) # y_u = CST(x, 1, deltasz=0, Au=fitted_Au) y_l = CST(x, 1, deltasz=0, Al=fitted_Al) # plt.plot(x, y_u, 'b') plt.plot(x, y_l, 'b') plt.show() # ============================================================================== # Shape parameter study # ============================================================================== n = 8 Data = shape_parameter_study(filename, n=n, solver='gradient', deltaz=0, objective='squared_mean', surface='lower') plt.figure()
i = closest[ii] print(i) x = designs[i]['x'] yl_morphing = designs[i]['yl'] yu_morphing = designs[i]['yu'] camber_morphing = (yu_morphing + yl_morphing) / 2. chord = max(x) current_rmse = 1e10 jjs = np.arange(0, len(Au_database)) # jjs = np.delete(jjs, 991) for j in jjs: Au = Au_database[j, :] Al = Al_database[j, :] y_database = CST(x, chord, deltasz=[du_database[j], dl_database[j]], Al=Al, Au=Au) camber_database = (y_database['u'] + y_database['l']) / 2. # rmse = np.sqrt(np.mean((camber_morphing - camber_database)**2)) rmse = np.sqrt( np.sum((yl_morphing - y_database['l'])**2 + (yu_morphing - y_database['u'])**2) / (2 * len(x))) error += 1 if rmse <= current_rmse: closest_database_i = { 'x': x, 'yl': y_database['l'], 'yu': y_database['u'], 'name': airfoil_database['names'][j], 'index': j,
s=100, c='k', marker='s', label='Centers') plt.xlabel(r'Angle of Attack (${}^\circ$)') plt.ylabel('Velocity (m/s)') plt.legend() plt.show() # ============================================================================== # Plot results # ============================================================================== plt.figure() np.set_printoptions(precision=20) x_p = np.linspace(0, c_P, 100000) y_p = CST(x_p, c_P, deltasz=[deltaz / 2., deltaz / 2.], Al=Al_P, Au=Au_P) for ii in range(len(closest)): i = closest[ii] d = designs[i] plt.plot(d['x'], d['yu'], colors[ii], label='%i' % ii, lw=2) plt.plot(d['x'], d['yl'], colors[ii], label=None, lw=2) plt.plot(x_p, y_p['u'], 'k--', label='Parent', lw=2) plt.plot(x_p, y_p['l'], 'k--', label=None, lw=2) plt.xlabel('$\psi^p$', fontsize=14) plt.ylabel(r'$\zeta^p$', fontsize=14) plt.ylim([-0.06, 0.17]) plt.grid() plt.gca().set_aspect('equal', adjustable='box') plt.legend(loc=1) plt.show()
def calculate_dependent_shape_coefficients(AC_u1, AC_u2, AC_u3, AC_u4, AC_u5, psi_spars, Au_P, Al_P, deltaz, c_P, morphing = 'backwards'): """Calculate dependent shape coefficients for children configuration for a 4 order Bernstein polynomial and return the children upper, lower shape coefficients, children chord and spar thicknesses. _P denotes parent parameters""" def calculate_AC_u0(AC_u0): Au_C = [AC_u0, AC_u1, AC_u2, AC_u3, AC_u4, AC_u5] c_C = calculate_c_baseline(c_P, Au_C, Au_P, deltaz) return np.sqrt(c_P/c_C)*Au_P[0] # Bersntein Polynomial def K(r,n): K=math.factorial(n)/(math.factorial(r)*math.factorial(n-r)) return K # Bernstein Polynomial order n = 5 # Find upper shape coefficient though iterative method since Au_0 is unknown # via fixed point iteration #AC_u0 = optimize.fixed_point(calculate_AC_u0, Au_P[0]) #print AC_u0 error = 9999 AC_u0 = Au_P[0] while error > 1e-9: before = AC_u0 AC_u0 = calculate_AC_u0(AC_u0) error = abs(AC_u0 - before) # Because the output is an array, need the extra [0] Au_C = [AC_u0, AC_u1, AC_u2, AC_u3, AC_u4, AC_u5] # Now that AC_u0 is known we can calculate the actual chord and AC_l0 c_C = calculate_c_baseline(c_P, Au_C, Au_P, deltaz/c_P) AC_l0 = np.sqrt(c_P/c_C)*Al_P[0] print('0 lower shape coefficient: ',AC_l0) # Calculate thicknessed and tensor B for the constraint linear system problem spar_thicknesses = [] A0 = AC_u0 + AC_l0 if morphing == 'backwards': b_list = np.zeros((n,1)) for j in range(len(psi_spars)): psi_j = psi_spars[j] #Calculate the spar thickness in meters from parent, afterwards, need to #adimensionalize for the goal airfoil by dividing by c_goal t_j = calculate_spar_distance(psi_spars[j], Au_C, Au_P, Al_P, deltaz, c_P) spar_thicknesses.append(t_j) b_list[j] = (t_j/c_C - psi_j*deltaz/c_C)/((psi_j**0.5)*(1-psi_j)) - A0*(1-psi_j)**n B = np.zeros((n,n)) #j is the row dimension and i the column dimension in this case for j in range(n): for i in range(n): #Because in Python counting starts at 0, need to add 1 to be #coherent for equations r = i +1 B[j][i] = K(r,n)*(psi_spars[j]**r)*(1-psi_spars[j])**(n-r) A_bar = np.dot(inv(B), b_list) Al_C = [AC_l0] for i in range(len(A_bar)): Al_C.append(A_bar[i][0] - Au_C[i+1]) #extra [0] is necessary because of array elif morphing == 'forwards': f = np.zeros((n,1)) # psi/xi coordinates for lower surface of the children configuration psi_lower_children = [] xi_lower_children = [] xi_upper_children = [] c_C = calculate_c_baseline(c_P, Au_C, Au_P, deltaz) # psi_baseline, Au_baseline, Au_goal, deltaz, c_baseline, c_goal psi_upper_children = [] for j in range(len(psi_spars)): psi_upper_children.append(calculate_psi_goal(psi_spars[j], Au_P, Au_C, deltaz, c_P, c_C)) # Calculate xi for upper children. Do not care about lower so just gave it random shape coefficients xi_upper_children = CST(psi_upper_children, 1., deltasz= [deltaz/2./c_C, deltaz/2./c_C], Al= Au_C, Au =Au_C) xi_upper_children = xi_upper_children['u'] print(xi_upper_children) #Debugging section x = np.linspace(0,1) y = CST(x, 1., deltasz= [deltaz/2./c_C, deltaz/2./c_C], Al= Au_C, Au =Au_C) # plt.plot(x,y['u']) # plt.scatter(psi_upper_children, xi_upper_children) # plt.grid() # plt.show() # BREAK for j in range(len(psi_spars)): xi_parent = CST(psi_spars, 1., deltasz= [deltaz/2./c_P, deltaz/2./c_P], Al= Al_P, Au =Au_P) delta_j_P = xi_parent['u'][j]-xi_parent['l'][j] t_j = c_P*(delta_j_P) # Claculate orientation for children s_j = calculate_spar_direction(psi_spars[j], Au_P, Au_C, deltaz, c_C) psi_l_j = psi_upper_children[j]-delta_j_P/c_C*s_j[0] xi_l_j = xi_upper_children[j]-delta_j_P/c_C*s_j[1] spar_thicknesses.append(t_j) psi_lower_children.append(psi_l_j) xi_lower_children.append(xi_l_j) f[j] = (2*xi_l_j + psi_l_j*deltaz/c_C)/(2*(psi_l_j**0.5)*(psi_l_j-1)) - AC_l0*(1-psi_l_j)**n F = np.zeros((n,n)) #j is the row dimension and i the column dimension in this case for j in range(n): for i in range(n): #Because in Python counting starts at 0, need to add 1 to be #coherent for equations r = i +1 F[j][i] = K(r,n)*(psi_lower_children[j]**r)*(1-psi_lower_children[j])**(n-r) print(F) print(f) A_lower = np.dot(inv(F), f) Al_C = [AC_l0] for i in range(len(A_lower)): Al_C.append(A_lower[i][0]) #extra [0] is necessary because of array return Au_C, Al_C, c_C, spar_thicknesses
def aircraft_range_LLT(AC, velocity, AOA): def to_integrate(weight): # velocity = 0.514444*108 # m/s (113 KTAS) span = 10.9728 RPM = 1800 a = 0.3089 # (lb/hr)/BTU b = 0.008 * RPM + 19.607 # lb/hr lbhr_to_kgs = 0.000125998 BHP_to_watt = 745.7 eta = 0.85 thrust = weight / lift_to_drag power_SI = thrust * velocity / eta power_BHP = power_SI / BHP_to_watt mass_flow = (a * power_BHP + b) mass_flow_SI = mass_flow * lbhr_to_kgs SFC = mass_flow_SI / thrust dR = velocity / g / SFC * lift_to_drag / weight return dR * 0.001 #*0.0005399 Au_P = [0.1828, 0.1179, 0.2079, 0.0850, 0.1874] Al_P = Au_P deltaz = 0 # Determine children shape coeffcients AC_u = list(data.values[i, 0:4]) Au_C, Al_C, c_C, spar_thicknesses = calculate_dependent_shape_coefficients( AC_u, psi_spars, Au_P, Al_P, deltaz, c_P, morphing=morphing_direction) # Calculate aerodynamics for that airfoil airfoil = 'optimal' x = create_x(1., distribution='linear') y = CST(x, 1., [deltaz / 2., deltaz / 2.], Al=Al_C, Au=Au_C) # Create file for Xfoil to read coordinates xf.create_input(x, y['u'], y['l'], airfoil, different_x_upper_lower=False) Data = xf.find_coefficients(airfoil, AOA, Reynolds=Reynolds(10000, velocity, c_C), iteration=100, NACA=False) deviation = 0.001 while Data['CL'] is None: Data_aft = xf.find_coefficients(airfoil, AOA * deviation, Reynolds=Reynolds( 10000, velocity, c_C), iteration=100, NACA=False) Data_fwd = xf.find_coefficients(airfoil, AOA * (1 - deviation), Reynolds=Reynolds( 10000, velocity, c_C), iteration=100, NACA=False) try: for key in Data: Data[key] = (Data_aft[key] + Data_fwd[key]) / 2. except: deviation += deviation alpha_L_0 = xf.find_alpha_L_0(airfoil, Reynolds=0, iteration=100, NACA=False) coefficients = LLT_calculator(alpha_L_0, Data['CD'], N=100, b=span, taper=1., chord_root=chord_root, alpha_root=AOA, V=velocity) lift_to_drag = coefficients['C_L'] / coefficients['C_D'] g = 9.81 # kg/ms fuel = 56 * 6.01 * 0.4535 * g initial_weight = 1111 * g final_weight = initial_weight - fuel return scipy.integrate.quad(to_integrate, final_weight, initial_weight)[0]