def fitting_shape_coefficients(filename, bounds='Default', n=5, return_data=False, return_error=False, optimize_deltaz=False): """Fit shape parameters to given data points Inputs: - filename: name of the file where the original data is - bounds: bounds for the shape parameters. If not defined, Default values are used. - n: order of the Bernstein polynomial. If bounds is default this input will define the order of the polynomial. Otherwise the length of bounds (minus one) is taken into consideration""" from hausdorff_distance import hausdorff_distance_2D 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 shape_difference_upper(inputs, optimize_deltaz = False): # if optimize_deltaz == True: # y = CST(x, 1, deltasz = inputs[-1]/2., Au = list(inputs[:-1])) # else: # y = CST(x, 1, deltasz = inputs[-1]/2., Au = list(inputs)) # # Vector to be compared with # b = {'x': x, 'y': y} # return hausdorff_distance_2D(a, b) # def shape_difference_lower(inputs, optimize_deltaz = False): # if optimize_deltaz == True: # y = CST(x, 1, deltasz = inputs[-1]/2., Al = list(inputs[:-1])) # else: # y = CST(x, 1, deltasz = deltaz/2., Al = list(inputs)) # # Vector to be compared with # b = {'x': x, 'y': y} # return hausdorff_distance_2D(a, b) def separate_upper_lower(data): for i in range(len(data['x'])): if data['y'][i] < 0: break upper = {'x': data['x'][0:i], 'y': data['y'][0:i]} lower = {'x': data['x'][i:], 'y': data['y'][i:]} return upper, lower # Order of Bernstein polynomial if bounds != 'Default': n = len(bounds) - 1 # Obtaining data data = output_reader(filename, separator=', ', header=['x', 'y']) # Rotating airfoil x_TE = (data['x'][0] + data['x'][-1]) / 2. y_TE = (data['y'][0] + data['y'][-1]) / 2. theta_TE = math.atan(-y_TE / x_TE) # position trailing edge at the x-axis processed_data = {'x': [], 'y': []} for i in range(len(data['x'])): x = data['x'][i] y = data['y'][i] c_theta = math.cos(theta_TE) s_theta = math.sin(theta_TE) x_rotated = c_theta * x - s_theta * y y_rotated = s_theta * x + c_theta * y processed_data['x'].append(x_rotated) processed_data['y'].append(y_rotated) data = processed_data # determine what is the leading edge and the rotation angle beta processed_data = {'x': [], 'y': []} min_x_list = [] min_y_list = [] min_x = min(data['x']) min_index = data['x'].index(min_x) min_y = data['y'][min_index] chord = max(data['x']) - min(data['x']) beta = math.atan((y_TE - min_y) / (x_TE - min_x)) for i in range(len(data['x'])): processed_data['x'].append((data['x'][i] - min_x) / chord) processed_data['y'].append(data['y'][i] / chord) data = processed_data #============================================================================== # Optimizing shape #============================================================================== # Determining default bounds if bounds == 'Default': upper_bounds = [[0, 1.]] * (n + 1) lower_bounds = [[0, 1]] + [[-1., 1.]] * n if optimize_deltaz: bounds = upper_bounds + lower_bounds + [[0, 0.1]] else: bounds = upper_bounds + lower_bounds deltaz = (data['y'][0] - data['y'][-1]) print(bounds) upper, lower = separate_upper_lower(data) # a = data # x = data['x'] result = differential_evolution(shape_difference, bounds, disp=True, popsize=10, args=[optimize_deltaz]) print('order %i upper done' % n) # x = lower['x'] # a = lower # result_lower = differential_evolution(shape_difference_lower, lower_bounds, # disp=True, popsize = 10, # args = (optimize_deltaz)) # print 'order %i lower done' % n if optimize_deltaz: Au = list(result.x[:n + 1]) Al = list(result.x[n + 1:-1]) deltaz = result.x[-1] else: Au = list(result.x[:n + 1]) Al = list(result.x[n + 1:]) # Return Al, Au, and others if return_data: return data, deltaz, Al, Au elif return_error: return result.fun, deltaz, Al, Au else: return deltaz, Al, Au
if __name__ == '__main__': import numpy as np import matplotlib.pyplot as plt import math # print find_3D_coefficients(airfoil='naca0012', alpha=1.) alpha = 0. x_hinge = 0.25/0.6175 deflection = -math.pi/2. #0.17453292519943295 #0.0010573527055 # generate original airfoil airfoil = "naca0012" xf.call(airfoil, output='Coordinates') filename = xf.file_name(airfoil, output='Coordinates') Data = xf.output_reader(filename, output='Coordinates', header = ['x','y']) Cm = calculate_flap_moment(Data['x'], Data['y'], alpha, x_hinge, deflection) V = 10 altitude = 10000 #feet Reynolds = ar.Reynolds(altitude, V, 1.0) deflection_list = list(np.linspace(5,30,4)) alpha_list = list(np.linspace(0,15,20)) # Calculate coefficients for without flap CL_list = [] CD_list = []
from aeropy.geometry.parametric import poly from aeropy.structural.stable_solution import (structure, mesh_1D, properties, boundary_conditions) from aeropy.xfoil_module import output_reader import matplotlib.pyplot as plt import matplotlib.cm as cm import numpy as np import pickle abaqus_primary = pickle.load(open("save.p", "rb"), encoding='latin1') abaqus_secondary = output_reader('secondary_variables.txt') # sort data abaqus_data = np.array( sorted( zip( abaqus_primary['C_U']['x'], abaqus_primary['C_U']['y'], abaqus_primary['U'][:, 0], abaqus_primary['U'][:, 1], ))) abq_x, abq_y, abq_u1, abq_u2 = abaqus_data.T abq_y = -abq_y + .005 abq_u2 = -abq_u2 # Convert log strains into engineering strain abaqus_secondary['LE11'] = np.exp(np.array(abaqus_secondary['LE11'])) - 1 abaqus_secondary['LE12'] = np.exp(np.array(abaqus_secondary['LE12'])) - 1 abaqus_secondary['LE22'] = np.exp(np.array(abaqus_secondary['LE22'])) - 1 coefficients = np.array([0, 0, 0, 0]) bp = properties()
def fitting_shape_coefficients(filename, bounds='Default', n=5, return_data=False, return_error=False, optimize_deltaz=False, solver='gradient', deltaz=None, objective='hausdorf', surface='both', x0=None): """Fit shape parameters to given data points Inputs: - filename: name of the file where the original data is - bounds: bounds for the shape parameters. If not defined, Default values are used. - n: order of the Bernstein polynomial. If bounds is default this input will define the order of the polynomial. Otherwise the length of bounds (minus one) is taken into consideration""" from optimization_tools.hausdorff_distance import hausdorff_distance_2D 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 separate_upper_lower(data): for key in data: data[key] = np.array(data[key]) index = np.where(data['y'] > 0) upper = {'x': data['x'][index], 'y': data['y'][index]} index = np.where(data['y'] <= 0) lower = {'x': data['x'][index], 'y': data['y'][index]} # x = data['x'] # y = data['y'] # for i in range(len(x)): # if data['y'][i] < 0: # break # upper = {'x': x[0:i], # 'y': y[0:i]} # lower = {'x': x[i:], # 'y': y[i:]} return upper, lower def _determine_bounds_x0(n, optimize_deltaz, bounds): if bounds == 'Default': upper_bounds = [[0, 1]] + [[-1., 1.]] * n lower_bounds = [[0, 1]] + [[-1., 1.]] * n if optimize_deltaz: if surface == 'both': bounds = upper_bounds + lower_bounds + [[0, 0.1]] x0 = (n + 1) * [ 0., ] + (n + 1) * [ 0., ] + [0.] elif surface == 'upper': bounds = upper_bounds + [[0, 0.1]] x0 = (n + 1) * [ 0., ] + [0.] elif surface == 'lower': bounds = lower_bounds + [[0, 0.1]] x0 = (n + 1) * [ 0., ] + [0.] else: bounds = upper_bounds + lower_bounds x0 = (n + 1) * [ 0., ] + (n + 1) * [ 0., ] return x0, bounds # Order of Bernstein polynomial if bounds != 'Default': n = len(bounds) - 1 # Obtaining data if filename[-2:] == '.p': import pickle data = pickle.load(open(filename, "rb"), encoding='latin1') data = data['wing'][list(data['wing'].keys())[3]] x, y, z = data.T else: data = output_reader(filename, separator='\t', header=['x', 'z']) x = data['x'] z = data['z'] # Rotating airfoil x_TE = (x[0] + x[-1]) / 2. y_TE = (z[0] + z[-1]) / 2. theta_TE = math.atan(-y_TE / x_TE) # position trailing edge at the x-axis processed_data = {'x': [], 'y': []} for i in range(len(x)): x_i = x[i] z_i = z[i] c_theta = math.cos(theta_TE) s_theta = math.sin(theta_TE) x_rotated = c_theta * x_i - s_theta * z_i z_rotated = s_theta * x_i + c_theta * z_i processed_data['x'].append(x_rotated) processed_data['y'].append(z_rotated) data = processed_data # determine what is the leading edge and the rotation angle beta processed_data = {'x': [], 'y': []} min_x = min(x) # min_index = data['x'].index(min_x) # min_y = data['y'][min_index] chord = max(x) - min(x) # beta = math.atan((y_TE - min_y)/(x_TE - min_x)) for i in range(len(x)): processed_data['x'].append((x[i] - min_x) / chord) processed_data['y'].append(z[i] / chord) data = processed_data # Determining default bounds x0_default, bounds = _determine_bounds_x0(n, optimize_deltaz, bounds) if x0 is None: x0 = x0_default if not optimize_deltaz and deltaz is None: deltaz = (data['y'][0] - data['y'][-1]) if surface == 'both': upper, lower = separate_upper_lower(data) elif surface == 'upper': upper = data elif surface == 'lower': lower = data # Calculate original error error0 = shape_difference(x0, optimize_deltaz=optimize_deltaz, surface=surface) def f(x): return shape_difference( x, optimize_deltaz=optimize_deltaz, surface=surface) / error0 # Optimize if solver == 'differential_evolution': result = differential_evolution(f, bounds, disp=True, popsize=10) x = result.x f = result.fun elif solver == 'gradient': solution = minimize(f, x0, bounds=bounds, options={ 'maxfun': 30000, 'eps': 1e-02 }) x = solution['x'] f = solution['fun'] print('order %i done' % n) # Unpackage data if surface == 'both' or surface == 'upper': Au = list(x[:n + 1]) if surface == 'both': if optimize_deltaz: Al = list(x[n + 1:-1]) deltaz = x[-1] else: Al = list(x[n + 1:]) elif surface == 'lower': Al = list(x[:n + 1]) # Return Al, Au, and others to_return = [] if return_data: to_return.append(data) if return_error: to_return.append(f) to_return.append(deltaz) if surface == 'lower' or surface == 'both': to_return.append(Al) elif surface == 'upper' or surface == 'both': to_return.append(Au) print(to_return) return to_return
return_error=True, deltaz=0, solver='differential_evolution', objective='squared_mean', 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',
import matplotlib.pyplot as plt from aeropy.airfoil_module import CST from aeropy.xfoil_module import output_reader data = pickle.load(open('shape_study.p', 'rb')) n = 5 print('For n=', n, ': ') print('\t error: ', data['error'][n - 1]) print('\t deltaz: ', data['deltaz'][n - 1]) print('\t Au: ', data['Au'][n - 1]) print('\t Al: ', data['Al'][n - 1]) filename = 'sampled_airfoil_data.csv' raw_data = output_reader(filename, separator=', ', header=['x', 'y']) # Rotating airfoil x_TE = (raw_data['x'][0] + raw_data['x'][-1]) / 2. y_TE = (raw_data['y'][0] + raw_data['y'][-1]) / 2. theta_TE = math.atan(-y_TE / x_TE) # position trailing edge at the x-axis processed_data = {'x': [], 'y': []} for i in range(len(raw_data['x'])): x = raw_data['x'][i] y = raw_data['y'][i] c_theta = math.cos(theta_TE) s_theta = math.sin(theta_TE) x_rotated = c_theta * x - s_theta * y