*ARCHIVED* development moved to aircraft-studio.
creator.py updated
Changed files
creator.py
@@ -105,8 +105,15 @@
105
105
106
106
107
107
class Airfoil(Coordinates):
108
Removed:
'''This class enables the creation of a single NACA airfoil.'''
108
Added:
'''
109
Added:
This class enables the creation of a single NACA airfoil.
109
110
111
Added:
Please note: the coordinates are saved as two lists
112
Added:
for the x- and z-coordinates. The coordinates start at
113
Added:
the leading edge, travel over the airfoil's upper edge,
114
Added:
then loops back to the leading edge via the lower edge.
115
Added:
'''
116
Added:
110
117
def __init__(self):
111
118
global parent
112
119
# Run 'Coordinates' super class init method with same chord & 1/2 span.
@@ -190,12 +197,9 @@
190
197
x_chord = [i / 10 for i in range(x_chord_25_percent * 10)]
191
198
x_chord.extend(i for i in range(x_chord_25_percent, self.chord + 1))
192
199
# Reversed list for our lower airfoil coordinate densification
193
Removed:
x_chord_rev = [i for i in range(
194
Removed:
self.chord, x_chord_25_percent, -1)]
200
Added:
x_chord_rev = [i for i in range(self.chord, x_chord_25_percent, -1)]
195
201
ext = [i / 10 for i in range(x_chord_25_percent * 10, -1, -1)]
196
202
x_chord_rev.extend(ext)
197
Removed:
print(len(x_chord))
198
Removed:
print(len(x_chord_rev))
199
203
200
204
# Generate our airfoil geometry from previous sub-functions.
201
205
for x in x_chord:
@@ -237,31 +241,21 @@
237
241
Return:
238
242
None
239
243
'''
240
Removed:
# Airfoil surface coordinates
241
Removed:
x = airfoil.x
242
Removed:
z = airfoil.z
244
Added:
243
245
# Scaled spar location with regards to chord
244
246
loc = x_loc_percent * self.chord
245
Removed:
# bisect_left: returns index of first value in x > loc
246
Removed:
# starting from [0]
247
Removed:
# bisect_right: returns index of first value in x > loc
248
Removed:
# starting from [-1] (last list element).
249
Removed:
# This ensures that the spar geom intersects with airfoil geom.
250
Removed:
spar_x_u = bi.bisect_left(x, loc) # index of spar's x_u
251
Removed:
spar_z_u = bi.bisect_left(z, loc)
252
Removed:
spar_x_l = bi.bisect_left(x[::-1], loc) # index of spar's x_l
253
Removed:
spar_z_l = bi.bisect_left(z[::-1], loc)
254
Removed:
print(len(x))
255
Removed:
print(len(z))
256
Removed:
# These x and y coordinates are assigned to the spar, NOT airfoil.
257
Removed:
# print(spar_x_u)
258
Removed:
# print(spar_z_u)
259
Removed:
# print(spar_x_l)
260
Removed:
# print(spar_z_l)
261
Removed:
# self.x.append(x[spar_x_u])
262
Removed:
# self.z.append(z[spar_z_u])
263
Removed:
# self.x.append(x[spar_x_l])
264
Removed:
# self.z.append(z[spar_z_l])
247
Added:
# bi.bisect_left: returns index of first value in airfoil.x > loc
248
Added:
# This ensures that spar geom intersects with airfoil geom.
249
Added:
# Spar upper coordinates
250
Added:
spar_x = bi.bisect_left(airfoil.x, loc) - 1
251
Added:
x = [airfoil.x[spar_x]]
252
Added:
z = [airfoil.z[spar_x]]
253
Added:
# Spar lower coordinates
254
Added:
spar_x = bi.bisect_left(airfoil.x[::-1], loc) - 1
255
Added:
x += [airfoil.x[-spar_x]]
256
Added:
z += [airfoil.z[-spar_x]]
257
Added:
self.x.append(x)
258
Added:
self.z.append(z)
265
259
return None
266
260
267
261
def add_spar_caps(self, spar_cap_area):
@@ -301,44 +295,44 @@
301
295
'''
302
296
303
297
# Find distance between leading edge and first upper stringer
304
Removed:
interval = airfoil.spar.x[0] / (stringer_u_1 + 1)
298
Added:
interval = airfoil.spar.x[0][0] / (stringer_u_1 + 1)
305
299
# initialise first self.stringer_x at first interval
306
300
x = interval
307
301
# Add upper stringers from leading edge until first spar.
308
302
for _ in range(0, stringer_u_1):
309
Removed:
# Index of the first value of airfoil_x > x
310
Removed:
index = bi.bisect_left(airfoil.x, x)
311
Removed:
self.x.append(airfoil.x[index])
312
Removed:
self.z.append(airfoil.z[index])
303
Added:
# Index of the first value of airfoil.x > x
304
Added:
i = bi.bisect_left(airfoil.x, x)
305
Added:
self.x.append(airfoil.x[i])
306
Added:
self.z.append(airfoil.z[i])
313
307
x += interval
314
308
# Add upper stringers from first spar until last spar
315
309
# TODO: stringer placement if only one spar is created
316
Removed:
interval = (airfoil.spar.x[-1]
317
Removed:
- airfoil.spar.x[0]) / (stringer_u_2 + 1)
318
Removed:
x = interval + airfoil.spar.x[0]
310
Added:
interval = (airfoil.spar.x[-1][0]
311
Added:
- airfoil.spar.x[0][0]) / (stringer_u_2 + 1)
312
Added:
x = interval + airfoil.spar.x[0][0]
319
313
for _ in range(0, stringer_u_2):
320
Removed:
index = bi.bisect_left(airfoil.x, x)
321
Removed:
self.x.append(airfoil.x[index])
322
Removed:
self.z.append(airfoil.z[index])
314
Added:
i = bi.bisect_left(airfoil.x, x)
315
Added:
self.x.append(airfoil.x[i])
316
Added:
self.z.append(airfoil.z[i])
323
317
x += interval
324
318
325
319
# Find distance between leading edge and first lower stringer
326
Removed:
interval = airfoil.spar.x[0] / (stringer_l_1 + 1)
320
Added:
interval = airfoil.spar.x[0][1] / (stringer_l_1 + 1)
327
321
x = interval
328
322
# Add lower stringers from leading edge until first spar.
329
323
for _ in range(0, stringer_l_1):
330
Removed:
index = bi.bisect_left(airfoil.x, x)
331
Removed:
self.x.append(airfoil.x[index])
332
Removed:
self.z.append(airfoil.z[index])
324
Added:
i = bi.bisect_left(airfoil.x[::-1], x)
325
Added:
self.x.append(airfoil.x[-i])
326
Added:
self.z.append(airfoil.z[-i])
333
327
x += interval
334
328
# Add lower stringers from first spar until last spar
335
Removed:
interval = (airfoil.spar.x[-1]
336
Removed:
- airfoil.spar.x[0]) / (stringer_l_2 + 1)
337
Removed:
x = interval + airfoil.spar.x[0]
329
Added:
interval = (airfoil.spar.x[-1][1]
330
Added:
- airfoil.spar.x[0][1]) / (stringer_l_2 + 1)
331
Added:
x = interval + airfoil.spar.x[0][1]
338
332
for _ in range(0, stringer_l_2):
339
Removed:
index = bi.bisect_left(airfoil.x, x)
340
Removed:
self.x.append(airfoil.x[index])
341
Removed:
self.z.append(airfoil.z[index])
333
Added:
i = bi.bisect_left(airfoil.x[::-1], x)
334
Added:
self.x.append(airfoil.x[-i])
335
Added:
self.z.append(airfoil.z[-i])
342
336
x += interval
343
337
return None
344
338
@@ -364,20 +358,20 @@
364
358
y_chord = [0, 0]
365
359
plt.plot(x_chord, y_chord, linewidth='1')
366
360
# Plot quarter chord
367
Removed:
plt.plot(airfoil.chord / 4, 0, '.', color='g',
361
Added:
plt.plot(airfoil.chord / 4, 0, '', color='g',
368
362
markersize=24, label='Quarter-chord')
369
363
# Plot mean camber line
370
364
plt.plot(airfoil.x_c, airfoil.y_c, '-.', color='r', linewidth='2',
371
365
label='Mean camber line')
372
366
# Plot airfoil surfaces
373
Removed:
plt.fill(airfoil.x, airfoil.z, '', color='b', linewidth='1', fill=False)
367
Added:
plt.fill(airfoil.x, airfoil.z, color='b', linewidth='1', fill=False)
374
368
375
369
# Plot spars
376
370
try:
377
Removed:
for _ in range(0, len(airfoil.spar.x)):
378
Removed:
x = (airfoil.spar.x[_], airfoil.spar.x[_])
379
Removed:
y = (airfoil.spar.z[_], airfoil.spar.z[_])
380
Removed:
plt.plot(x, y, '.-', color='b')
371
Added:
for _ in range(len(airfoil.spar.x)):
372
Added:
x = (airfoil.spar.x[_])
373
Added:
y = (airfoil.spar.z[_])
374
Added:
plt.plot(x, y, '-', color='b')
381
375
except AttributeError:
382
376
print('No spars to plot.')
383
377
# Plot upper stringers
main.py
@@ -24,7 +24,7 @@
24
24
25
25
# Airfoil dimensions
26
26
NACA_NUM = 2412
27
Removed:
CHORD_LENGTH = 12
27
Added:
CHORD_LENGTH = 100
28
28
SEMI_SPAN = 20
29
29
30
30
# Airfoil thickness
@@ -41,10 +41,10 @@
41
41
STRINGER_AREA = 0.1 # sqin
42
42
43
43
# Amount of stringers
44
Removed:
TOP_STRINGERS = 2
45
Removed:
BOTTOM_STRINGERS = 18
46
Removed:
NOSE_TOP_STRINGERS = 5
47
Removed:
NOSE_BOTTOM_STRINGERS = 5
44
Added:
TOP_STRINGERS = 4
45
Added:
BOTTOM_STRINGERS = 7
46
Added:
NOSE_TOP_STRINGERS = 3
47
Added:
NOSE_BOTTOM_STRINGERS = 6
48
48
49
49
# population information & save path
50
50
POP_SIZE = 1
@@ -73,29 +73,29 @@
73
73
# af.info_print(2)
74
74
af.info_save(SAVE_PATH, _)
75
75
76
Removed:
# # Create spar instance
77
Removed:
# af.spar = creator.Spar()
78
Removed:
# # Define the spar coordinates and mass, stored in single spar object
79
Removed:
# af.spar.add_coord(af, 0.15)
80
Removed:
# af.spar.add_coord(af, 0.55)
81
Removed:
# # Automatically adds spar caps for all spars previously defined
82
Removed:
# af.spar.add_spar_caps(SPAR_CAP_AREA)
83
Removed:
# af.spar.add_mass(SPAR_MASS)
84
Removed:
# # af.spar.info_print(2)
85
Removed:
# # af.spar.info_save(SAVE_PATH, _)
86
Removed:
#
87
Removed:
# # Create stringer instance
88
Removed:
# af.stringer = creator.Stringer()
89
Removed:
# # Compute the stringer coordinates from their quantity in each zone
90
Removed:
# af.stringer.add_coord(af,
91
Removed:
# NOSE_TOP_STRINGERS,
92
Removed:
# TOP_STRINGERS,
93
Removed:
# NOSE_BOTTOM_STRINGERS,
94
Removed:
# BOTTOM_STRINGERS)
95
Removed:
# af.stringer.add_area(STRINGER_AREA)
96
Removed:
# af.stringer.add_mass(STRINGER_MASS)
97
Removed:
# # af.stringer.info_print(2)
98
Removed:
# # af.stringer.info_save(SAVE_PATH, _)
76
Added:
# Create spar instance
77
Added:
af.spar = creator.Spar()
78
Added:
# Define the spar coordinates and mass, stored in single spar object
79
Added:
af.spar.add_coord(af, 0.20)
80
Added:
af.spar.add_coord(af, 0.65)
81
Added:
# Automatically adds spar caps for all spars previously defined
82
Added:
af.spar.add_spar_caps(SPAR_CAP_AREA)
83
Added:
af.spar.add_mass(SPAR_MASS)
84
Added:
# af.spar.info_print(2)
85
Added:
af.spar.info_save(SAVE_PATH, _)
86
Added:
87
Added:
# Create stringer instance
88
Added:
af.stringer = creator.Stringer()
89
Added:
# Compute the stringer coordinates from their quantity in each zone
90
Added:
af.stringer.add_coord(af,
91
Added:
NOSE_TOP_STRINGERS,
92
Added:
TOP_STRINGERS,
93
Added:
NOSE_BOTTOM_STRINGERS,
94
Added:
BOTTOM_STRINGERS)
95
Added:
af.stringer.add_area(STRINGER_AREA)
96
Added:
af.stringer.add_mass(STRINGER_MASS)
97
Added:
# af.stringer.info_print(2)
98
Added:
af.stringer.info_save(SAVE_PATH, _)
99
99
100
100
# Plot components with matplotlib
101
101
creator.plot_geom(af)