From b47414d08a70749e84ccc925e9e3a9761c81e0e3 Mon Sep 17 00:00:00 2001 From: Marius Peter Date: Sat, 22 Jun 2019 20:01:26 -0700 Subject: start work --- creator.py | 147 +++++++++++++++++++++++++++++------------------------------ evaluator.py | 52 ++++++++++----------- 2 files changed, 98 insertions(+), 101 deletions(-) diff --git a/creator.py b/creator.py index 78c537d..d75661f 100644 --- a/creator.py +++ b/creator.py @@ -53,14 +53,9 @@ class Coordinates: self.area = float() # Component material self.material = str() - # Upper coordinates - self.x_u = [] - self.z_u = [] - # Lower coordinates - self.x_l = [] - self.z_l = [] - # Coordinates x_u, z_u, x_l, z_l packed in single list - self.coord = [] + # Coordinates + self.x = [] + self.z = [] # The airfoil components know the Coordinates instance's coords global parent @@ -85,10 +80,8 @@ class Coordinates: print('Semi-span:', self.semi_span) print('Mass:', self.mass) print(num_of_dashes * '-') - print('x_u the upper x-coordinates:\n', np.around(self.x_u, round)) - print('z_u the upper z-coordinates:\n', np.around(self.z_u, round)) - print('x_l the lower x-coordinates:\n', np.around(self.x_l, round)) - print('z_l the lower z-coordinates:\n', np.around(self.z_l, round)) + print('x-coordinates:\n', np.around(self.x, round)) + print('z-coordinates:\n', np.around(self.z, round)) return None def info_save(self, save_path, number): @@ -182,14 +175,14 @@ class Airfoil(Coordinates): return theta def get_upper_coord(x): - x_u = x - get_thickness(x) * sin(get_theta(x)) - z_u = get_camber(x) + get_thickness(x) * cos(get_theta(x)) - return (x_u, z_u) + x = x - get_thickness(x) * sin(get_theta(x)) + z = get_camber(x) + get_thickness(x) * cos(get_theta(x)) + return (x, z) def get_lower_coord(x): - x_l = x + get_thickness(x) * sin(get_theta(x)) - z_l = get_camber(x) - get_thickness(x) * cos(get_theta(x)) - return (x_l, z_l) + x = x + get_thickness(x) * sin(get_theta(x)) + z = get_camber(x) - get_thickness(x) * cos(get_theta(x)) + return (x, z) # Densify x-coordinates 10 times for first 1/4 chord length x_chord_25_percent = round(self.chord / 4) @@ -200,10 +193,13 @@ class Airfoil(Coordinates): for x in x_chord: self.x_c.append(x) self.y_c.append(get_camber(x)) - self.x_u.append(get_upper_coord(x)[0]) - self.z_u.append(get_upper_coord(x)[1]) - self.x_l.append(get_lower_coord(x)[0]) - self.z_l.append(get_lower_coord(x)[1]) + self.x.append(get_upper_coord(x)[0]) + self.z.append(get_upper_coord(x)[1]) + # Behold the true power of Python list slicing! + # (This special list index reverses the list.) + for x in x_chord[::-1]: + self.x.append(get_lower_coord(x)[0]) + self.z.append(get_lower_coord(x)[1]) return None def add_mass(self, mass): @@ -211,8 +207,8 @@ class Airfoil(Coordinates): def info_print(self, round): super().info_print(round) - print('x_c the camber x-coordinates:\n', np.around(self.x_u, round)) - print('z_c the camber z-coordinates:\n', np.around(self.x_u, round)) + print('x_c the camber x-coordinates:\n', np.around(self.x, round)) + print('z_c the camber z-coordinates:\n', np.around(self.x, round)) return None @@ -223,12 +219,12 @@ class Spar(Coordinates): def __init__(self): super().__init__(parent.chord, parent.semi_span) - def add_coord(self, airfoil, spar_x): + def add_coord(self, airfoil, x_loc_percent): ''' Add a single spar at the % chord location given to function. Parameters: - coordinates: provided by Airfoil.coordinates[x_u, z_u, x_l, z_l]. + coordinates: provided by Airfoil.coordinates[x, z, x, z]. material: spar's material. Assumes homogeneous material. spar_x: spar's location as a % of total chord length. @@ -237,21 +233,22 @@ class Spar(Coordinates): ''' # Airfoil surface coordinates # unpacked from 'coordinates' (list of lists in 'Coordinates'). - x_u = airfoil.x_u - z_u = airfoil.z_u - x_l = airfoil.x_l - z_l = airfoil.z_l + x = airfoil.x + z = airfoil.z # Scaled spar location with regards to chord - loc = spar_x * self.chord - # bisect_left: returns index of first value in x_u > loc. - # Ensures that the spar coordinates intersect with airfoil surface. - spar_x_u = bi.bisect_left(x_u, loc) # index of spar's x_u - spar_x_l = bi.bisect_left(x_l, loc) # index of spar's x_l + loc = x_loc_percent * self.chord + # bisect_left: returns index of first value in x > loc + # starting from [0] + # bisect_right: returns index of first value in x > loc + # starting from [-1] (last list element). + # This ensures that the spar geom intersects with airfoil geom. + spar_x = bi.bisect_left(x, loc) # index of spar's x + spar_x = bi.bisect_left(x, loc) # index of spar's x # These x and y coordinates are assigned to the spar, NOT airfoil. - self.x_u.append(x_u[spar_x_u]) - self.z_u.append(z_u[spar_x_u]) - self.x_l.append(x_l[spar_x_l]) - self.z_l.append(z_l[spar_x_l]) + self.x.append(x[spar_x]) + self.z.append(z[spar_x]) + self.x.append(x[spar_x]) + self.z.append(z[spar_x]) return None def add_spar_caps(self, spar_cap_area): @@ -259,7 +256,7 @@ class Spar(Coordinates): return None def add_mass(self, mass): - self.mass = len(self.x_u) * mass + self.mass = len(self.x) * mass return None @@ -291,44 +288,44 @@ class Stringer(Coordinates): ''' # Find distance between leading edge and first upper stringer - interval = airfoil.spar.x_u[0] / (stringer_u_1 + 1) - # initialise first self.stringer_x_u at first interval + interval = airfoil.spar.x[0] / (stringer_u_1 + 1) + # initialise first self.stringer_x at first interval x = interval # Add upper stringers from leading edge until first spar. for _ in range(0, stringer_u_1): - # Index of the first value of airfoil_x_u > x - index = bi.bisect_left(airfoil.x_u, x) - self.x_u.append(airfoil.x_u[index]) - self.z_u.append(airfoil.z_u[index]) + # Index of the first value of airfoil_x > x + index = bi.bisect_left(airfoil.x, x) + self.x.append(airfoil.x[index]) + self.z.append(airfoil.z[index]) x += interval # Add upper stringers from first spar until last spar # TODO: stringer placement if only one spar is created - interval = (airfoil.spar.x_u[-1] - - airfoil.spar.x_u[0]) / (stringer_u_2 + 1) - x = interval + airfoil.spar.x_u[0] + interval = (airfoil.spar.x[-1] + - airfoil.spar.x[0]) / (stringer_u_2 + 1) + x = interval + airfoil.spar.x[0] for _ in range(0, stringer_u_2): - index = bi.bisect_left(airfoil.x_u, x) - self.x_u.append(airfoil.x_u[index]) - self.z_u.append(airfoil.z_u[index]) + index = bi.bisect_left(airfoil.x, x) + self.x.append(airfoil.x[index]) + self.z.append(airfoil.z[index]) x += interval # Find distance between leading edge and first lower stringer - interval = airfoil.spar.x_l[0] / (stringer_l_1 + 1) + interval = airfoil.spar.x[0] / (stringer_l_1 + 1) x = interval # Add lower stringers from leading edge until first spar. for _ in range(0, stringer_l_1): - index = bi.bisect_left(airfoil.x_l, x) - self.x_l.append(airfoil.x_l[index]) - self.z_l.append(airfoil.z_l[index]) + index = bi.bisect_left(airfoil.x, x) + self.x.append(airfoil.x[index]) + self.z.append(airfoil.z[index]) x += interval # Add lower stringers from first spar until last spar - interval = (airfoil.spar.x_l[-1] - - airfoil.spar.x_l[0]) / (stringer_l_2 + 1) - x = interval + airfoil.spar.x_l[0] + interval = (airfoil.spar.x[-1] + - airfoil.spar.x[0]) / (stringer_l_2 + 1) + x = interval + airfoil.spar.x[0] for _ in range(0, stringer_l_2): - index = bi.bisect_left(airfoil.x_l, x) - self.x_l.append(airfoil.x_l[index]) - self.z_l.append(airfoil.z_l[index]) + index = bi.bisect_left(airfoil.x, x) + self.x.append(airfoil.x[index]) + self.z.append(airfoil.z[index]) x += interval return None @@ -337,7 +334,7 @@ class Stringer(Coordinates): return None def add_mass(self, mass): - self.mass = len(self.x_u) * mass + len(self.x_l) * mass + self.mass = len(self.x) * mass + len(self.x) * mass return None def info_print(self, round): @@ -361,34 +358,34 @@ def plot_geom(airfoil): '-.', color='r', linewidth='2', label='Mean camber line') # Plot upper surface - plt.plot(airfoil.x_u, airfoil.z_u, + plt.plot(airfoil.x, airfoil.z, '', color='b', linewidth='1') # Plot lower surface - plt.plot(airfoil.x_l, airfoil.z_l, + plt.plot(airfoil.x, airfoil.z, '', color='b', linewidth='1') # Plot spars - for _ in range(0, len(airfoil.spar.x_u)): - x = (airfoil.spar.x_u[_], airfoil.spar.x_l[_]) - y = (airfoil.spar.z_u[_], airfoil.spar.z_l[_]) + for _ in range(0, len(airfoil.spar.x)): + x = (airfoil.spar.x[_], airfoil.spar.x[_]) + y = (airfoil.spar.z[_], airfoil.spar.z[_]) plt.plot(x, y, '.-', color='b') # Plot upper stringers - for _ in range(0, len(airfoil.stringer.x_u)): - x = airfoil.stringer.x_u[_] - y = airfoil.stringer.z_u[_] + for _ in range(0, len(airfoil.stringer.x)): + x = airfoil.stringer.x[_] + y = airfoil.stringer.z[_] plt.plot(x, y, '.', color='y', markersize=12) # Plot lower stringers - for _ in range(0, len(airfoil.stringer.x_l)): - x = airfoil.stringer.x_l[_] - y = airfoil.stringer.z_l[_] + for _ in range(0, len(airfoil.stringer.x)): + x = airfoil.stringer.x[_] + y = airfoil.stringer.z[_] plt.plot(x, y, '.', color='y', markersize=12) # Graph formatting plt.xlabel('X axis') plt.ylabel('Z axis') - plot_bound = airfoil.x_u[-1] + plot_bound = airfoil.x[-1] plt.xlim(- 0.10 * plot_bound, 1.10 * plot_bound) plt.ylim(- (1.10 * plot_bound / 2), (1.10 * plot_bound / 2)) plt.gca().set_aspect('equal', adjustable='box') diff --git a/evaluator.py b/evaluator.py index 5710522..801c5ae 100644 --- a/evaluator.py +++ b/evaluator.py @@ -39,11 +39,11 @@ class Evaluator: + airfoil.stringer.mass) self.mass_dist = [] # Upper coordinates - self.x_u = airfoil.x_u - self.z_u = airfoil.z_u + self.x = airfoil.x + self.z = airfoil.z # Lower coordinates - self.x_l = airfoil.x_l - self.z_l = airfoil.z_l + self.x = airfoil.x + self.z = airfoil.z self.lift_rectangular = [] self.lift_elliptical = [] self.lift_total = [] @@ -140,15 +140,15 @@ class Evaluator: stringer_area = self.stringer.area caps_area = self.spar.cap_area - x_spars = self.spar.x_u + self.spar.x_l - x_stringers = self.stringer.x_u + self.stringer.x_l - z_stringers = self.stringer.z_u + self.stringer.z_l + x_spars = self.spar.x + self.spar.x + x_stringers = self.stringer.x + self.stringer.x + z_stringers = self.stringer.z + self.stringer.z denom = float(len(x_spars) * caps_area + len(x_stringers) * stringer_area) - x_ctr = (sum([i * caps_area for i in self.spar.x_u]) + x_ctr = (sum([i * caps_area for i in self.spar.x]) + sum([i * stringer_area for i in x_stringers])) / denom - z_ctr = (sum([i * caps_area for i in self.spar.z_u]) + z_ctr = (sum([i * caps_area for i in self.spar.z]) + sum([i * stringer_area for i in z_stringers])) / denom return(x_ctr, z_ctr) @@ -159,12 +159,12 @@ class Evaluator: caps_area = self.spar.cap_area # Adds upper and lower components' coordinates to list - x_stringers = self.stringer.x_u + self.stringer.x_l - z_stringers = self.stringer.z_u + self.stringer.z_l - x_spars = self.spar.x_u + self.spar.x_l - z_spars = self.spar.z_u + self.spar.z_l + x_stringers = self.stringer.x + self.stringer.x + z_stringers = self.stringer.z + self.stringer.z + x_spars = self.spar.x + self.spar.x + z_spars = self.spar.z + self.spar.z stringer_count = range(len(x_stringers)) - spar_count = range(len(self.spar.x_u)) + spar_count = range(len(self.spar.x)) # I_x is the sum of the contributions of the spar caps and stringers I_x = (sum([caps_area * (z_spars[i] - self.centroid[1]) ** 2 @@ -212,27 +212,27 @@ def plot_geom(evaluator): q = evaluator.chord / 4 plt.plot(q, 0, '.', color='g', markersize=24, label='Quarter-chord') # Plot upper surface - plt.plot(evaluator.x_u, evaluator.z_u, + plt.plot(evaluator.x, evaluator.z, '', color='b', linewidth='1') # Plot lower surface - plt.plot(evaluator.x_l, evaluator.z_l, + plt.plot(evaluator.x, evaluator.z, '', color='b', linewidth='1') # Plot spars - for _ in range(0, len(evaluator.spar.x_u)): - x = (evaluator.spar.x_u[_], evaluator.spar.x_l[_]) - y = (evaluator.spar.z_u[_], evaluator.spar.z_l[_]) + for _ in range(0, len(evaluator.spar.x)): + x = (evaluator.spar.x[_], evaluator.spar.x[_]) + y = (evaluator.spar.z[_], evaluator.spar.z[_]) plt.plot(x, y, '.-', color='b') # Plot upper stringers - for _ in range(0, len(evaluator.stringer.x_u)): - x = evaluator.stringer.x_u[_] - y = evaluator.stringer.z_u[_] + for _ in range(0, len(evaluator.stringer.x)): + x = evaluator.stringer.x[_] + y = evaluator.stringer.z[_] plt.plot(x, y, '.', color='y', markersize=12) # Plot lower stringers - for _ in range(0, len(evaluator.stringer.x_l)): - x = evaluator.stringer.x_l[_] - y = evaluator.stringer.z_l[_] + for _ in range(0, len(evaluator.stringer.x)): + x = evaluator.stringer.x[_] + y = evaluator.stringer.z[_] plt.plot(x, y, '.', color='y', markersize=12) # Plot centroid @@ -244,7 +244,7 @@ def plot_geom(evaluator): plt.xlabel('X axis') plt.ylabel('Z axis') - plot_bound = evaluator.x_u[-1] + plot_bound = evaluator.x[-1] plt.xlim(- 0.10 * plot_bound, 1.10 * plot_bound) plt.ylim(- (1.10 * plot_bound / 2), (1.10 * plot_bound / 2)) plt.gca().set_aspect('equal', adjustable='box') -- cgit v1.2.3 From 2c8e6e632eb03cd6545de51d72aaebe0df9bf7ee Mon Sep 17 00:00:00 2001 From: Marius Peter Date: Sat, 22 Jun 2019 21:07:02 -0700 Subject: airfoil coordinates --- creator.py | 85 +++++++++++++++++++++++++++++++++++--------------------------- main.py | 68 ++++++++++++++++++++++++------------------------- 2 files changed, 82 insertions(+), 71 deletions(-) diff --git a/creator.py b/creator.py index d75661f..601e849 100644 --- a/creator.py +++ b/creator.py @@ -186,8 +186,16 @@ class Airfoil(Coordinates): # Densify x-coordinates 10 times for first 1/4 chord length x_chord_25_percent = round(self.chord / 4) - x_chord = [x / 10 for x in range(x_chord_25_percent * 10)] - x_chord.extend([x for x in range(x_chord_25_percent, self.chord + 1)]) + + x_chord = [i / 10 for i in range(x_chord_25_percent * 10)] + x_chord.extend(i for i in range(x_chord_25_percent, self.chord + 1)) + # Reversed list for our lower airfoil coordinate densification + x_chord_rev = [i for i in range( + self.chord, x_chord_25_percent, -1)] + ext = [i / 10 for i in range(x_chord_25_percent * 10, -1, -1)] + x_chord_rev.extend(ext) + print(len(x_chord)) + print(len(x_chord_rev)) # Generate our airfoil geometry from previous sub-functions. for x in x_chord: @@ -195,9 +203,7 @@ class Airfoil(Coordinates): self.y_c.append(get_camber(x)) self.x.append(get_upper_coord(x)[0]) self.z.append(get_upper_coord(x)[1]) - # Behold the true power of Python list slicing! - # (This special list index reverses the list.) - for x in x_chord[::-1]: + for x in x_chord_rev: self.x.append(get_lower_coord(x)[0]) self.z.append(get_lower_coord(x)[1]) return None @@ -232,7 +238,6 @@ class Spar(Coordinates): None ''' # Airfoil surface coordinates - # unpacked from 'coordinates' (list of lists in 'Coordinates'). x = airfoil.x z = airfoil.z # Scaled spar location with regards to chord @@ -242,13 +247,21 @@ class Spar(Coordinates): # bisect_right: returns index of first value in x > loc # starting from [-1] (last list element). # This ensures that the spar geom intersects with airfoil geom. - spar_x = bi.bisect_left(x, loc) # index of spar's x - spar_x = bi.bisect_left(x, loc) # index of spar's x + spar_x_u = bi.bisect_left(x, loc) # index of spar's x_u + spar_z_u = bi.bisect_left(z, loc) + spar_x_l = bi.bisect_left(x[::-1], loc) # index of spar's x_l + spar_z_l = bi.bisect_left(z[::-1], loc) + print(len(x)) + print(len(z)) # These x and y coordinates are assigned to the spar, NOT airfoil. - self.x.append(x[spar_x]) - self.z.append(z[spar_x]) - self.x.append(x[spar_x]) - self.z.append(z[spar_x]) + # print(spar_x_u) + # print(spar_z_u) + # print(spar_x_l) + # print(spar_z_l) + # self.x.append(x[spar_x_u]) + # self.z.append(z[spar_z_u]) + # self.x.append(x[spar_x_l]) + # self.z.append(z[spar_z_l]) return None def add_spar_caps(self, spar_cap_area): @@ -354,40 +367,38 @@ def plot_geom(airfoil): plt.plot(airfoil.chord / 4, 0, '.', color='g', markersize=24, label='Quarter-chord') # Plot mean camber line - plt.plot(airfoil.x_c, airfoil.y_c, - '-.', color='r', linewidth='2', + plt.plot(airfoil.x_c, airfoil.y_c, '-.', color='r', linewidth='2', label='Mean camber line') - # Plot upper surface - plt.plot(airfoil.x, airfoil.z, - '', color='b', linewidth='1') - # Plot lower surface - plt.plot(airfoil.x, airfoil.z, - '', color='b', linewidth='1') + # Plot airfoil surfaces + plt.fill(airfoil.x, airfoil.z, '', color='b', linewidth='1', fill=False) # Plot spars - for _ in range(0, len(airfoil.spar.x)): - x = (airfoil.spar.x[_], airfoil.spar.x[_]) - y = (airfoil.spar.z[_], airfoil.spar.z[_]) - plt.plot(x, y, '.-', color='b') - + try: + for _ in range(0, len(airfoil.spar.x)): + x = (airfoil.spar.x[_], airfoil.spar.x[_]) + y = (airfoil.spar.z[_], airfoil.spar.z[_]) + plt.plot(x, y, '.-', color='b') + except AttributeError: + print('No spars to plot.') # Plot upper stringers - for _ in range(0, len(airfoil.stringer.x)): - x = airfoil.stringer.x[_] - y = airfoil.stringer.z[_] - plt.plot(x, y, '.', color='y', markersize=12) - # Plot lower stringers - for _ in range(0, len(airfoil.stringer.x)): - x = airfoil.stringer.x[_] - y = airfoil.stringer.z[_] - plt.plot(x, y, '.', color='y', markersize=12) + try: + for _ in range(0, len(airfoil.stringer.x)): + x = airfoil.stringer.x[_] + y = airfoil.stringer.z[_] + plt.plot(x, y, '.', color='y', markersize=12) + except AttributeError: + print('No stringers to plot.') + # # Plot lower stringers + # for _ in range(0, len(airfoil.stringer.x)): + # x = airfoil.stringer.x[_] + # y = airfoil.stringer.z[_] + # plt.plot(x, y, '.', color='y', markersize=12) # Graph formatting plt.xlabel('X axis') plt.ylabel('Z axis') - plot_bound = airfoil.x[-1] - plt.xlim(- 0.10 * plot_bound, 1.10 * plot_bound) - plt.ylim(- (1.10 * plot_bound / 2), (1.10 * plot_bound / 2)) + # plot_bound = airfoil.x[-1] plt.gca().set_aspect('equal', adjustable='box') plt.gca().legend() plt.grid(axis='both', linestyle=':', linewidth=1) diff --git a/main.py b/main.py index fd8855f..09d33e6 100644 --- a/main.py +++ b/main.py @@ -24,8 +24,8 @@ start_time = time.time() # Airfoil dimensions NACA_NUM = 2412 -CHORD_LENGTH = 40 -SEMI_SPAN = 50 +CHORD_LENGTH = 12 +SEMI_SPAN = 20 # Airfoil thickness T_UPPER = 0.1 @@ -41,9 +41,9 @@ SPAR_CAP_AREA = 0.3 # sqin STRINGER_AREA = 0.1 # sqin # Amount of stringers -TOP_STRINGERS = 0 +TOP_STRINGERS = 2 BOTTOM_STRINGERS = 18 -NOSE_TOP_STRINGERS = 0 +NOSE_TOP_STRINGERS = 5 NOSE_BOTTOM_STRINGERS = 5 # population information & save path @@ -71,42 +71,42 @@ def main(): af.add_naca(NACA_NUM) af.add_mass(AIRFOIL_MASS) # af.info_print(2) - # af.info_save(SAVE_PATH, _) - - # Create spar instance - af.spar = creator.Spar() - # Define the spar coordinates and mass, stored in single spar object - af.spar.add_coord(af, 0.15) - af.spar.add_coord(af, 0.55) - # Automatically adds spar caps for all spars previously defined - af.spar.add_spar_caps(SPAR_CAP_AREA) - af.spar.add_mass(SPAR_MASS) - # af.spar.info_print(2) - # af.spar.info_save(SAVE_PATH, _) - - # Create stringer instance - af.stringer = creator.Stringer() - # Compute the stringer coordinates from their quantity in each zone - af.stringer.add_coord(af, - NOSE_TOP_STRINGERS, - TOP_STRINGERS, - NOSE_BOTTOM_STRINGERS, - BOTTOM_STRINGERS) - af.stringer.add_area(STRINGER_AREA) - af.stringer.add_mass(STRINGER_MASS) - # af.stringer.info_print(2) - # af.stringer.info_save(SAVE_PATH, _) + af.info_save(SAVE_PATH, _) + + # # Create spar instance + # af.spar = creator.Spar() + # # Define the spar coordinates and mass, stored in single spar object + # af.spar.add_coord(af, 0.15) + # af.spar.add_coord(af, 0.55) + # # Automatically adds spar caps for all spars previously defined + # af.spar.add_spar_caps(SPAR_CAP_AREA) + # af.spar.add_mass(SPAR_MASS) + # # af.spar.info_print(2) + # # af.spar.info_save(SAVE_PATH, _) + # + # # Create stringer instance + # af.stringer = creator.Stringer() + # # Compute the stringer coordinates from their quantity in each zone + # af.stringer.add_coord(af, + # NOSE_TOP_STRINGERS, + # TOP_STRINGERS, + # NOSE_BOTTOM_STRINGERS, + # BOTTOM_STRINGERS) + # af.stringer.add_area(STRINGER_AREA) + # af.stringer.add_mass(STRINGER_MASS) + # # af.stringer.info_print(2) + # # af.stringer.info_save(SAVE_PATH, _) # Plot components with matplotlib - # creator.plot_geom(af) + creator.plot_geom(af) # Evaluator object contains airfoil analysis results. - eval = evaluator.Evaluator(af) + # eval = evaluator.Evaluator(af) # The analysis is performed in the evaluator.py module. - eval.analysis() + # eval.analysis() # eval.info_print(2) - eval.info_save(SAVE_PATH, _) - evaluator.plot_geom(eval) + # eval.info_save(SAVE_PATH, _) + # evaluator.plot_geom(eval) # evaluator.plot_lift(eval) # Print final execution time -- cgit v1.2.3 From 5de63cf149ba044444531e7a5eb5a40ec67dcaed Mon Sep 17 00:00:00 2001 From: Marius Peter Date: Sun, 23 Jun 2019 01:45:58 -0700 Subject: creator.py updated --- creator.py | 104 +++++++++++++++++++++++++++++-------------------------------- main.py | 56 ++++++++++++++++----------------- 2 files changed, 77 insertions(+), 83 deletions(-) diff --git a/creator.py b/creator.py index 601e849..210e502 100644 --- a/creator.py +++ b/creator.py @@ -105,7 +105,14 @@ class Coordinates: class Airfoil(Coordinates): - '''This class enables the creation of a single NACA airfoil.''' + ''' + This class enables the creation of a single NACA airfoil. + + Please note: the coordinates are saved as two lists + for the x- and z-coordinates. The coordinates start at + the leading edge, travel over the airfoil's upper edge, + then loops back to the leading edge via the lower edge. + ''' def __init__(self): global parent @@ -190,12 +197,9 @@ class Airfoil(Coordinates): x_chord = [i / 10 for i in range(x_chord_25_percent * 10)] x_chord.extend(i for i in range(x_chord_25_percent, self.chord + 1)) # Reversed list for our lower airfoil coordinate densification - x_chord_rev = [i for i in range( - self.chord, x_chord_25_percent, -1)] + x_chord_rev = [i for i in range(self.chord, x_chord_25_percent, -1)] ext = [i / 10 for i in range(x_chord_25_percent * 10, -1, -1)] x_chord_rev.extend(ext) - print(len(x_chord)) - print(len(x_chord_rev)) # Generate our airfoil geometry from previous sub-functions. for x in x_chord: @@ -237,31 +241,21 @@ class Spar(Coordinates): Return: None ''' - # Airfoil surface coordinates - x = airfoil.x - z = airfoil.z + # Scaled spar location with regards to chord loc = x_loc_percent * self.chord - # bisect_left: returns index of first value in x > loc - # starting from [0] - # bisect_right: returns index of first value in x > loc - # starting from [-1] (last list element). - # This ensures that the spar geom intersects with airfoil geom. - spar_x_u = bi.bisect_left(x, loc) # index of spar's x_u - spar_z_u = bi.bisect_left(z, loc) - spar_x_l = bi.bisect_left(x[::-1], loc) # index of spar's x_l - spar_z_l = bi.bisect_left(z[::-1], loc) - print(len(x)) - print(len(z)) - # These x and y coordinates are assigned to the spar, NOT airfoil. - # print(spar_x_u) - # print(spar_z_u) - # print(spar_x_l) - # print(spar_z_l) - # self.x.append(x[spar_x_u]) - # self.z.append(z[spar_z_u]) - # self.x.append(x[spar_x_l]) - # self.z.append(z[spar_z_l]) + # bi.bisect_left: returns index of first value in airfoil.x > loc + # This ensures that spar geom intersects with airfoil geom. + # Spar upper coordinates + spar_x = bi.bisect_left(airfoil.x, loc) - 1 + x = [airfoil.x[spar_x]] + z = [airfoil.z[spar_x]] + # Spar lower coordinates + spar_x = bi.bisect_left(airfoil.x[::-1], loc) - 1 + x += [airfoil.x[-spar_x]] + z += [airfoil.z[-spar_x]] + self.x.append(x) + self.z.append(z) return None def add_spar_caps(self, spar_cap_area): @@ -301,44 +295,44 @@ class Stringer(Coordinates): ''' # Find distance between leading edge and first upper stringer - interval = airfoil.spar.x[0] / (stringer_u_1 + 1) + interval = airfoil.spar.x[0][0] / (stringer_u_1 + 1) # initialise first self.stringer_x at first interval x = interval # Add upper stringers from leading edge until first spar. for _ in range(0, stringer_u_1): - # Index of the first value of airfoil_x > x - index = bi.bisect_left(airfoil.x, x) - self.x.append(airfoil.x[index]) - self.z.append(airfoil.z[index]) + # Index of the first value of airfoil.x > x + i = bi.bisect_left(airfoil.x, x) + self.x.append(airfoil.x[i]) + self.z.append(airfoil.z[i]) x += interval # Add upper stringers from first spar until last spar # TODO: stringer placement if only one spar is created - interval = (airfoil.spar.x[-1] - - airfoil.spar.x[0]) / (stringer_u_2 + 1) - x = interval + airfoil.spar.x[0] + interval = (airfoil.spar.x[-1][0] + - airfoil.spar.x[0][0]) / (stringer_u_2 + 1) + x = interval + airfoil.spar.x[0][0] for _ in range(0, stringer_u_2): - index = bi.bisect_left(airfoil.x, x) - self.x.append(airfoil.x[index]) - self.z.append(airfoil.z[index]) + i = bi.bisect_left(airfoil.x, x) + self.x.append(airfoil.x[i]) + self.z.append(airfoil.z[i]) x += interval # Find distance between leading edge and first lower stringer - interval = airfoil.spar.x[0] / (stringer_l_1 + 1) + interval = airfoil.spar.x[0][1] / (stringer_l_1 + 1) x = interval # Add lower stringers from leading edge until first spar. for _ in range(0, stringer_l_1): - index = bi.bisect_left(airfoil.x, x) - self.x.append(airfoil.x[index]) - self.z.append(airfoil.z[index]) + i = bi.bisect_left(airfoil.x[::-1], x) + self.x.append(airfoil.x[-i]) + self.z.append(airfoil.z[-i]) x += interval # Add lower stringers from first spar until last spar - interval = (airfoil.spar.x[-1] - - airfoil.spar.x[0]) / (stringer_l_2 + 1) - x = interval + airfoil.spar.x[0] + interval = (airfoil.spar.x[-1][1] + - airfoil.spar.x[0][1]) / (stringer_l_2 + 1) + x = interval + airfoil.spar.x[0][1] for _ in range(0, stringer_l_2): - index = bi.bisect_left(airfoil.x, x) - self.x.append(airfoil.x[index]) - self.z.append(airfoil.z[index]) + i = bi.bisect_left(airfoil.x[::-1], x) + self.x.append(airfoil.x[-i]) + self.z.append(airfoil.z[-i]) x += interval return None @@ -364,20 +358,20 @@ def plot_geom(airfoil): y_chord = [0, 0] plt.plot(x_chord, y_chord, linewidth='1') # Plot quarter chord - plt.plot(airfoil.chord / 4, 0, '.', color='g', + plt.plot(airfoil.chord / 4, 0, '', color='g', markersize=24, label='Quarter-chord') # Plot mean camber line plt.plot(airfoil.x_c, airfoil.y_c, '-.', color='r', linewidth='2', label='Mean camber line') # Plot airfoil surfaces - plt.fill(airfoil.x, airfoil.z, '', color='b', linewidth='1', fill=False) + plt.fill(airfoil.x, airfoil.z, color='b', linewidth='1', fill=False) # Plot spars try: - for _ in range(0, len(airfoil.spar.x)): - x = (airfoil.spar.x[_], airfoil.spar.x[_]) - y = (airfoil.spar.z[_], airfoil.spar.z[_]) - plt.plot(x, y, '.-', color='b') + for _ in range(len(airfoil.spar.x)): + x = (airfoil.spar.x[_]) + y = (airfoil.spar.z[_]) + plt.plot(x, y, '-', color='b') except AttributeError: print('No spars to plot.') # Plot upper stringers diff --git a/main.py b/main.py index 09d33e6..2f1ba1f 100644 --- a/main.py +++ b/main.py @@ -24,7 +24,7 @@ start_time = time.time() # Airfoil dimensions NACA_NUM = 2412 -CHORD_LENGTH = 12 +CHORD_LENGTH = 100 SEMI_SPAN = 20 # Airfoil thickness @@ -41,10 +41,10 @@ SPAR_CAP_AREA = 0.3 # sqin STRINGER_AREA = 0.1 # sqin # Amount of stringers -TOP_STRINGERS = 2 -BOTTOM_STRINGERS = 18 -NOSE_TOP_STRINGERS = 5 -NOSE_BOTTOM_STRINGERS = 5 +TOP_STRINGERS = 4 +BOTTOM_STRINGERS = 7 +NOSE_TOP_STRINGERS = 3 +NOSE_BOTTOM_STRINGERS = 6 # population information & save path POP_SIZE = 1 @@ -73,29 +73,29 @@ def main(): # af.info_print(2) af.info_save(SAVE_PATH, _) - # # Create spar instance - # af.spar = creator.Spar() - # # Define the spar coordinates and mass, stored in single spar object - # af.spar.add_coord(af, 0.15) - # af.spar.add_coord(af, 0.55) - # # Automatically adds spar caps for all spars previously defined - # af.spar.add_spar_caps(SPAR_CAP_AREA) - # af.spar.add_mass(SPAR_MASS) - # # af.spar.info_print(2) - # # af.spar.info_save(SAVE_PATH, _) - # - # # Create stringer instance - # af.stringer = creator.Stringer() - # # Compute the stringer coordinates from their quantity in each zone - # af.stringer.add_coord(af, - # NOSE_TOP_STRINGERS, - # TOP_STRINGERS, - # NOSE_BOTTOM_STRINGERS, - # BOTTOM_STRINGERS) - # af.stringer.add_area(STRINGER_AREA) - # af.stringer.add_mass(STRINGER_MASS) - # # af.stringer.info_print(2) - # # af.stringer.info_save(SAVE_PATH, _) + # Create spar instance + af.spar = creator.Spar() + # Define the spar coordinates and mass, stored in single spar object + af.spar.add_coord(af, 0.20) + af.spar.add_coord(af, 0.65) + # Automatically adds spar caps for all spars previously defined + af.spar.add_spar_caps(SPAR_CAP_AREA) + af.spar.add_mass(SPAR_MASS) + # af.spar.info_print(2) + af.spar.info_save(SAVE_PATH, _) + + # Create stringer instance + af.stringer = creator.Stringer() + # Compute the stringer coordinates from their quantity in each zone + af.stringer.add_coord(af, + NOSE_TOP_STRINGERS, + TOP_STRINGERS, + NOSE_BOTTOM_STRINGERS, + BOTTOM_STRINGERS) + af.stringer.add_area(STRINGER_AREA) + af.stringer.add_mass(STRINGER_MASS) + # af.stringer.info_print(2) + af.stringer.info_save(SAVE_PATH, _) # Plot components with matplotlib creator.plot_geom(af) -- cgit v1.2.3 From 3074c4c8cbeac6a6e5a4d7fa4a8afe34ec39911d Mon Sep 17 00:00:00 2001 From: Marius Peter Date: Sun, 23 Jun 2019 02:09:34 -0700 Subject: finalised branch :) --- creator.py | 6 +++-- evaluator.py | 76 ++++++++++++++++++++++++++++++++---------------------------- main.py | 20 ++++++++-------- 3 files changed, 54 insertions(+), 48 deletions(-) diff --git a/creator.py b/creator.py index 210e502..aa9fcbd 100644 --- a/creator.py +++ b/creator.py @@ -358,7 +358,7 @@ def plot_geom(airfoil): y_chord = [0, 0] plt.plot(x_chord, y_chord, linewidth='1') # Plot quarter chord - plt.plot(airfoil.chord / 4, 0, '', color='g', + plt.plot(airfoil.chord / 4, 0, '.', color='g', markersize=24, label='Quarter-chord') # Plot mean camber line plt.plot(airfoil.x_c, airfoil.y_c, '-.', color='r', linewidth='2', @@ -392,7 +392,9 @@ def plot_geom(airfoil): plt.xlabel('X axis') plt.ylabel('Z axis') - # plot_bound = airfoil.x[-1] + plot_bound = max(airfoil.x) + plt.xlim(- 0.10 * plot_bound, 1.10 * plot_bound) + plt.ylim(- (1.10 * plot_bound / 2), (1.10 * plot_bound / 2)) plt.gca().set_aspect('equal', adjustable='box') plt.gca().legend() plt.grid(axis='both', linestyle=':', linewidth=1) diff --git a/evaluator.py b/evaluator.py index 801c5ae..867ede9 100644 --- a/evaluator.py +++ b/evaluator.py @@ -137,19 +137,21 @@ class Evaluator: def get_centroid(self): '''Return the coordinates of the centroid.''' + stringer_area = self.stringer.area caps_area = self.spar.cap_area - x_spars = self.spar.x + self.spar.x - x_stringers = self.stringer.x + self.stringer.x - z_stringers = self.stringer.z + self.stringer.z - denom = float(len(x_spars) * caps_area - + len(x_stringers) * stringer_area) + spar_x = self.spar.x + self.spar.x + stringers_x = self.stringer.x + stringers_z = self.stringer.z + + denom = float(len(spar_x) * caps_area + + len(stringers_x) * stringer_area) - x_ctr = (sum([i * caps_area for i in self.spar.x]) - + sum([i * stringer_area for i in x_stringers])) / denom - z_ctr = (sum([i * caps_area for i in self.spar.z]) - + sum([i * stringer_area for i in z_stringers])) / denom + x_ctr = (sum([i * caps_area for i in spar_x[:][0]]) + + sum([i * stringer_area for i in stringers_x])) / denom + z_ctr = (sum([i * caps_area for i in spar_x[:][0]]) + + sum([i * stringer_area for i in stringers_z])) / denom return(x_ctr, z_ctr) def get_inertia_terms(self): @@ -159,10 +161,11 @@ class Evaluator: caps_area = self.spar.cap_area # Adds upper and lower components' coordinates to list - x_stringers = self.stringer.x + self.stringer.x - z_stringers = self.stringer.z + self.stringer.z - x_spars = self.spar.x + self.spar.x - z_spars = self.spar.z + self.spar.z + x_stringers = self.stringer.x + z_stringers = self.stringer.z + x_spars = self.spar.x[:][0] + self.spar.x[:][1] + z_spars = self.spar.z[:][0] + self.spar.z[:][1] + print(x_spars) stringer_count = range(len(x_stringers)) spar_count = range(len(self.spar.x)) @@ -209,31 +212,32 @@ def plot_geom(evaluator): y_chord = [0, 0] plt.plot(x_chord, y_chord, linewidth='1') # Plot quarter chord - q = evaluator.chord / 4 - plt.plot(q, 0, '.', color='g', markersize=24, label='Quarter-chord') - # Plot upper surface - plt.plot(evaluator.x, evaluator.z, - '', color='b', linewidth='1') - # Plot lower surface - plt.plot(evaluator.x, evaluator.z, - '', color='b', linewidth='1') + plt.plot(evaluator.chord / 4, 0, '.', color='g', + markersize=24, label='Quarter-chord') + # Plot airfoil surfaces + plt.fill(evaluator.x, evaluator.z, color='b', linewidth='1', fill=False) # Plot spars - for _ in range(0, len(evaluator.spar.x)): - x = (evaluator.spar.x[_], evaluator.spar.x[_]) - y = (evaluator.spar.z[_], evaluator.spar.z[_]) - plt.plot(x, y, '.-', color='b') - + try: + for _ in range(len(evaluator.spar.x)): + x = (evaluator.spar.x[_]) + y = (evaluator.spar.z[_]) + plt.plot(x, y, '-', color='b') + except AttributeError: + print('No spars to plot.') # Plot upper stringers - for _ in range(0, len(evaluator.stringer.x)): - x = evaluator.stringer.x[_] - y = evaluator.stringer.z[_] - plt.plot(x, y, '.', color='y', markersize=12) - # Plot lower stringers - for _ in range(0, len(evaluator.stringer.x)): - x = evaluator.stringer.x[_] - y = evaluator.stringer.z[_] - plt.plot(x, y, '.', color='y', markersize=12) + try: + for _ in range(0, len(evaluator.stringer.x)): + x = evaluator.stringer.x[_] + y = evaluator.stringer.z[_] + plt.plot(x, y, '.', color='y', markersize=12) + except AttributeError: + print('No stringers to plot.') + # # Plot lower stringers + # for _ in range(0, len(evaluator.stringer.x)): + # x = evaluator.stringer.x[_] + # y = evaluator.stringer.z[_] + # plt.plot(x, y, '.', color='y', markersize=12) # Plot centroid x = evaluator.centroid[0] @@ -244,7 +248,7 @@ def plot_geom(evaluator): plt.xlabel('X axis') plt.ylabel('Z axis') - plot_bound = evaluator.x[-1] + plot_bound = max(evaluator.x) plt.xlim(- 0.10 * plot_bound, 1.10 * plot_bound) plt.ylim(- (1.10 * plot_bound / 2), (1.10 * plot_bound / 2)) plt.gca().set_aspect('equal', adjustable='box') diff --git a/main.py b/main.py index 2f1ba1f..b62b24f 100644 --- a/main.py +++ b/main.py @@ -25,7 +25,7 @@ start_time = time.time() # Airfoil dimensions NACA_NUM = 2412 CHORD_LENGTH = 100 -SEMI_SPAN = 20 +SEMI_SPAN = 140 # Airfoil thickness T_UPPER = 0.1 @@ -41,8 +41,8 @@ SPAR_CAP_AREA = 0.3 # sqin STRINGER_AREA = 0.1 # sqin # Amount of stringers -TOP_STRINGERS = 4 -BOTTOM_STRINGERS = 7 +TOP_STRINGERS = 5 +BOTTOM_STRINGERS = 4 NOSE_TOP_STRINGERS = 3 NOSE_BOTTOM_STRINGERS = 6 @@ -71,7 +71,7 @@ def main(): af.add_naca(NACA_NUM) af.add_mass(AIRFOIL_MASS) # af.info_print(2) - af.info_save(SAVE_PATH, _) + # af.info_save(SAVE_PATH, _) # Create spar instance af.spar = creator.Spar() @@ -82,7 +82,7 @@ def main(): af.spar.add_spar_caps(SPAR_CAP_AREA) af.spar.add_mass(SPAR_MASS) # af.spar.info_print(2) - af.spar.info_save(SAVE_PATH, _) + # af.spar.info_save(SAVE_PATH, _) # Create stringer instance af.stringer = creator.Stringer() @@ -95,17 +95,17 @@ def main(): af.stringer.add_area(STRINGER_AREA) af.stringer.add_mass(STRINGER_MASS) # af.stringer.info_print(2) - af.stringer.info_save(SAVE_PATH, _) + # af.stringer.info_save(SAVE_PATH, _) # Plot components with matplotlib - creator.plot_geom(af) + # creator.plot_geom(af) # Evaluator object contains airfoil analysis results. - # eval = evaluator.Evaluator(af) + eval = evaluator.Evaluator(af) # The analysis is performed in the evaluator.py module. - # eval.analysis() + eval.analysis() # eval.info_print(2) - # eval.info_save(SAVE_PATH, _) + eval.info_save(SAVE_PATH, _) # evaluator.plot_geom(eval) # evaluator.plot_lift(eval) -- cgit v1.2.3 From 7a7c4840386adc45ed84985784d57fe3fc345c07 Mon Sep 17 00:00:00 2001 From: Marius Peter Date: Sun, 23 Jun 2019 02:17:21 -0700 Subject: bugfix --- creator.py | 4 ++-- main.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/creator.py b/creator.py index aa9fcbd..0bfe529 100644 --- a/creator.py +++ b/creator.py @@ -198,8 +198,8 @@ class Airfoil(Coordinates): x_chord.extend(i for i in range(x_chord_25_percent, self.chord + 1)) # Reversed list for our lower airfoil coordinate densification x_chord_rev = [i for i in range(self.chord, x_chord_25_percent, -1)] - ext = [i / 10 for i in range(x_chord_25_percent * 10, -1, -1)] - x_chord_rev.extend(ext) + extend = [i / 10 for i in range(x_chord_25_percent * 10, -1, -1)] + x_chord_rev.extend(extend) # Generate our airfoil geometry from previous sub-functions. for x in x_chord: diff --git a/main.py b/main.py index b62b24f..97cd492 100644 --- a/main.py +++ b/main.py @@ -23,8 +23,8 @@ import time start_time = time.time() # Airfoil dimensions -NACA_NUM = 2412 -CHORD_LENGTH = 100 +NACA_NUM = 4412 +CHORD_LENGTH = 133 SEMI_SPAN = 140 # Airfoil thickness @@ -106,7 +106,7 @@ def main(): eval.analysis() # eval.info_print(2) eval.info_save(SAVE_PATH, _) - # evaluator.plot_geom(eval) + evaluator.plot_geom(eval) # evaluator.plot_lift(eval) # Print final execution time -- cgit v1.2.3 From 3ce3509ea818c289d45de8264068791de91a1b99 Mon Sep 17 00:00:00 2001 From: Marius Peter Date: Sun, 23 Jun 2019 12:17:37 -0700 Subject: bugfix: negative x-coord error for high-camber cases --- creator.py | 37 ++++++++++++++++--------------------- evaluator.py | 23 ++++++++++++++--------- main.py | 18 +++++++++--------- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/creator.py b/creator.py index 0bfe529..3749bf7 100644 --- a/creator.py +++ b/creator.py @@ -122,7 +122,7 @@ class Airfoil(Coordinates): self.naca_num = int() # Mean camber line self.x_c = [] - self.y_c = [] + self.z_c = [] def add_naca(self, naca_num): ''' @@ -148,22 +148,22 @@ class Airfoil(Coordinates): def get_camber(x): ''' - Returns camber y-coordinate from 1 'x' along the airfoil chord. + Returns camber z-coordinate from 1 'x' along the airfoil chord. ''' - y_c = float() + z_c = float() if 0 <= x < p_c: - y_c = (m / (p ** 2)) * (2 * p * (x / self.chord) + z_c = (m / (p ** 2)) * (2 * p * (x / self.chord) - (x / self.chord) ** 2) elif p_c <= x <= self.chord: - y_c = (m / ((1 - p) ** 2)) * ((1 - 2 * p) + z_c = (m / ((1 - p) ** 2)) * ((1 - 2 * p) + 2 * p * (x / self.chord) - (x / self.chord) ** 2) - return (y_c * self.chord) + return (z_c * self.chord) def get_thickness(x): - ''' - Returns thickness from 1 'x' along the airfoil chord. - ''' + '''Returns thickness from 1 'x' along the airfoil chord.''' + + x = 0 if x < 0 else x y_t = 5 * t * self.chord * ( + 0.2969 * sqrt(x / self.chord) - 0.1260 * (x / self.chord) @@ -173,12 +173,12 @@ class Airfoil(Coordinates): return y_t def get_theta(x): - dy_c = float() + dz_c = float() if 0 <= x < p_c: - dy_c = ((2 * m) / p ** 2) * (p - x / self.chord) + dz_c = ((2 * m) / p ** 2) * (p - x / self.chord) elif p_c <= x <= self.chord: - dy_c = (2 * m) / ((1 - p) ** 2) * (p - x / self.chord) - theta = atan(dy_c) + dz_c = (2 * m) / ((1 - p) ** 2) * (p - x / self.chord) + theta = atan(dz_c) return theta def get_upper_coord(x): @@ -204,7 +204,7 @@ class Airfoil(Coordinates): # Generate our airfoil geometry from previous sub-functions. for x in x_chord: self.x_c.append(x) - self.y_c.append(get_camber(x)) + self.z_c.append(get_camber(x)) self.x.append(get_upper_coord(x)[0]) self.z.append(get_upper_coord(x)[1]) for x in x_chord_rev: @@ -361,7 +361,7 @@ def plot_geom(airfoil): plt.plot(airfoil.chord / 4, 0, '.', color='g', markersize=24, label='Quarter-chord') # Plot mean camber line - plt.plot(airfoil.x_c, airfoil.y_c, '-.', color='r', linewidth='2', + plt.plot(airfoil.x_c, airfoil.z_c, '-.', color='r', linewidth='2', label='Mean camber line') # Plot airfoil surfaces plt.fill(airfoil.x, airfoil.z, color='b', linewidth='1', fill=False) @@ -374,7 +374,7 @@ def plot_geom(airfoil): plt.plot(x, y, '-', color='b') except AttributeError: print('No spars to plot.') - # Plot upper stringers + # Plot stringers try: for _ in range(0, len(airfoil.stringer.x)): x = airfoil.stringer.x[_] @@ -382,11 +382,6 @@ def plot_geom(airfoil): plt.plot(x, y, '.', color='y', markersize=12) except AttributeError: print('No stringers to plot.') - # # Plot lower stringers - # for _ in range(0, len(airfoil.stringer.x)): - # x = airfoil.stringer.x[_] - # y = airfoil.stringer.z[_] - # plt.plot(x, y, '.', color='y', markersize=12) # Graph formatting plt.xlabel('X axis') diff --git a/evaluator.py b/evaluator.py index 867ede9..9512a4b 100644 --- a/evaluator.py +++ b/evaluator.py @@ -49,6 +49,8 @@ class Evaluator: self.lift_total = [] # Drag self.drag = [] + # centroid + self.centroid = [] # Inertia terms: # I_x = self.I_[0] # I_z = self.I_[1] @@ -141,18 +143,22 @@ class Evaluator: stringer_area = self.stringer.area caps_area = self.spar.cap_area - spar_x = self.spar.x + self.spar.x + caps_x = [value for spar in self.spar.x for value in spar] + caps_z = [value for spar in self.spar.z for value in spar] stringers_x = self.stringer.x stringers_z = self.stringer.z - denom = float(len(spar_x) * caps_area - + len(stringers_x) * stringer_area) + denominator = float(len(caps_x) * caps_area + + len(stringers_x) * stringer_area) - x_ctr = (sum([i * caps_area for i in spar_x[:][0]]) - + sum([i * stringer_area for i in stringers_x])) / denom - z_ctr = (sum([i * caps_area for i in spar_x[:][0]]) - + sum([i * stringer_area for i in stringers_z])) / denom - return(x_ctr, z_ctr) + centroid_x = float(sum([x * caps_area for x in caps_x]) + + sum([x * stringer_area for x in stringers_x])) + centroid_x = centroid_x / denominator + + centroid_z = float(sum([z * caps_area for z in caps_z]) + + sum([z * stringer_area for z in stringers_z])) + centroid_z = centroid_z / denominator + return(centroid_x, centroid_z) def get_inertia_terms(self): '''Obtain all inertia terms.''' @@ -165,7 +171,6 @@ class Evaluator: z_stringers = self.stringer.z x_spars = self.spar.x[:][0] + self.spar.x[:][1] z_spars = self.spar.z[:][0] + self.spar.z[:][1] - print(x_spars) stringer_count = range(len(x_stringers)) spar_count = range(len(self.spar.x)) diff --git a/main.py b/main.py index 97cd492..f82ca89 100644 --- a/main.py +++ b/main.py @@ -23,9 +23,9 @@ import time start_time = time.time() # Airfoil dimensions -NACA_NUM = 4412 -CHORD_LENGTH = 133 -SEMI_SPAN = 140 +NACA_NUM = 2412 +CHORD_LENGTH = 101 +SEMI_SPAN = 40 # Airfoil thickness T_UPPER = 0.1 @@ -37,11 +37,11 @@ SPAR_MASS = 10 # lbs STRINGER_MASS = 5 # lbs # Area -SPAR_CAP_AREA = 0.3 # sqin +SPAR_CAP_AREA = 0.0 # sqin STRINGER_AREA = 0.1 # sqin # Amount of stringers -TOP_STRINGERS = 5 +TOP_STRINGERS = 3 BOTTOM_STRINGERS = 4 NOSE_TOP_STRINGERS = 3 NOSE_BOTTOM_STRINGERS = 6 @@ -71,7 +71,7 @@ def main(): af.add_naca(NACA_NUM) af.add_mass(AIRFOIL_MASS) # af.info_print(2) - # af.info_save(SAVE_PATH, _) + af.info_save(SAVE_PATH, _) # Create spar instance af.spar = creator.Spar() @@ -82,7 +82,7 @@ def main(): af.spar.add_spar_caps(SPAR_CAP_AREA) af.spar.add_mass(SPAR_MASS) # af.spar.info_print(2) - # af.spar.info_save(SAVE_PATH, _) + af.spar.info_save(SAVE_PATH, _) # Create stringer instance af.stringer = creator.Stringer() @@ -95,7 +95,7 @@ def main(): af.stringer.add_area(STRINGER_AREA) af.stringer.add_mass(STRINGER_MASS) # af.stringer.info_print(2) - # af.stringer.info_save(SAVE_PATH, _) + af.stringer.info_save(SAVE_PATH, _) # Plot components with matplotlib # creator.plot_geom(af) @@ -106,7 +106,7 @@ def main(): eval.analysis() # eval.info_print(2) eval.info_save(SAVE_PATH, _) - evaluator.plot_geom(eval) + # evaluator.plot_geom(eval) # evaluator.plot_lift(eval) # Print final execution time -- cgit v1.2.3 From 70116a396caa2ae02b857f751a4df31886592795 Mon Sep 17 00:00:00 2001 From: Marius Peter Date: Sun, 23 Jun 2019 12:21:32 -0700 Subject: Airfoil docstring --- creator.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/creator.py b/creator.py index 3749bf7..d378c35 100644 --- a/creator.py +++ b/creator.py @@ -112,6 +112,9 @@ class Airfoil(Coordinates): for the x- and z-coordinates. The coordinates start at the leading edge, travel over the airfoil's upper edge, then loops back to the leading edge via the lower edge. + This method was chosen for easier future exports + to 3D CAD packages like SolidWorks, which can import + geometry as coordinates written in a CSV file. ''' def __init__(self): -- cgit v1.2.3 From 84bc9ff5fd93a011cb05df7ccc0b2797f9d3847d Mon Sep 17 00:00:00 2001 From: Marius Peter Date: Sun, 23 Jun 2019 12:22:30 -0700 Subject: typos in Airfoil docstring --- creator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/creator.py b/creator.py index d378c35..533f35e 100644 --- a/creator.py +++ b/creator.py @@ -111,7 +111,7 @@ class Airfoil(Coordinates): Please note: the coordinates are saved as two lists for the x- and z-coordinates. The coordinates start at the leading edge, travel over the airfoil's upper edge, - then loops back to the leading edge via the lower edge. + then loop back to the leading edge via the lower edge. This method was chosen for easier future exports to 3D CAD packages like SolidWorks, which can import geometry as coordinates written in a CSV file. -- cgit v1.2.3 From d9b627d06abe7f3d53aa3aebfecd9e392b3e276e Mon Sep 17 00:00:00 2001 From: Marius Peter Date: Sun, 23 Jun 2019 12:24:23 -0700 Subject: Airfoil docstring --- creator.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/creator.py b/creator.py index 533f35e..6dd3c1c 100644 --- a/creator.py +++ b/creator.py @@ -112,8 +112,9 @@ class Airfoil(Coordinates): for the x- and z-coordinates. The coordinates start at the leading edge, travel over the airfoil's upper edge, then loop back to the leading edge via the lower edge. + This method was chosen for easier future exports - to 3D CAD packages like SolidWorks, which can import + to 3D CAD packages like SolidWorks, which can import such geometry as coordinates written in a CSV file. ''' -- cgit v1.2.3 From 4e562fba0de3f00b5240e6e09176ee73584f620f Mon Sep 17 00:00:00 2001 From: Marius Peter Date: Sun, 23 Jun 2019 12:28:22 -0700 Subject: redundant corodinates --- evaluator.py | 5 +---- main.py | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/evaluator.py b/evaluator.py index 9512a4b..eea4f67 100644 --- a/evaluator.py +++ b/evaluator.py @@ -38,10 +38,7 @@ class Evaluator: + airfoil.spar.mass + airfoil.stringer.mass) self.mass_dist = [] - # Upper coordinates - self.x = airfoil.x - self.z = airfoil.z - # Lower coordinates + # Coordinates self.x = airfoil.x self.z = airfoil.z self.lift_rectangular = [] diff --git a/main.py b/main.py index f82ca89..f11bd0f 100644 --- a/main.py +++ b/main.py @@ -98,7 +98,7 @@ def main(): af.stringer.info_save(SAVE_PATH, _) # Plot components with matplotlib - # creator.plot_geom(af) + creator.plot_geom(af) # Evaluator object contains airfoil analysis results. eval = evaluator.Evaluator(af) @@ -106,7 +106,7 @@ def main(): eval.analysis() # eval.info_print(2) eval.info_save(SAVE_PATH, _) - # evaluator.plot_geom(eval) + evaluator.plot_geom(eval) # evaluator.plot_lift(eval) # Print final execution time -- cgit v1.2.3 From c9dde0aa778331bc110dc1e223cb76816847a08c Mon Sep 17 00:00:00 2001 From: Marius Peter Date: Sun, 23 Jun 2019 12:28:45 -0700 Subject: lift --- evaluator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/evaluator.py b/evaluator.py index eea4f67..046d4dd 100644 --- a/evaluator.py +++ b/evaluator.py @@ -41,6 +41,7 @@ class Evaluator: # Coordinates self.x = airfoil.x self.z = airfoil.z + # Lift self.lift_rectangular = [] self.lift_elliptical = [] self.lift_total = [] -- cgit v1.2.3