summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBlendoit <51464356+Blendoit@users.noreply.github.com>2019-06-06 16:41:17 -0700
committerGitHub <noreply@github.com>2019-06-06 16:41:17 -0700
commita5e80fc53745e2a8696c3f0ef588979b282ef216 (patch)
tree9932e9df986f45153161f1346a131c377acc7963
parent330a9bbba9de5e88aab6ed5c1c5c95cd48231814 (diff)
Delete creator.py
-rw-r--r--creator.py382
1 files changed, 0 insertions, 382 deletions
diff --git a/creator.py b/creator.py
deleted file mode 100644
index 59c8436..0000000
--- a/creator.py
+++ /dev/null
@@ -1,382 +0,0 @@
-# This file is part of Marius Peter's airfoil analysis package (this program).
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-import sys
-import os.path
-import numpy as np
-from math import sin, cos, tan, atan, sqrt, ceil
-import bisect as bi
-import matplotlib.pyplot as plt
-import matplotlib as mpl
-from mpl_toolkits.mplot3d import Axes3D
-
-
-# This variable is required for main.py constant wing dimensions
-# to be passed to inheriting classes (Airfoil, Spar, Stringer, Rib).
-# This way, we don't have to redeclare our coordinates as parameters for
-# our spars, stringers and ribs. This makes for more elegant code.
-global parent
-
-
-class Coordinates:
- """
- All classes need coordinates relative to the chord & semi-span.
- So, they all inherit from this class.
- """
-
- def __init__(self, chord, semi_span):
- # Global dimensions
- self.chord = chord
- self.semi_span = semi_span
- # Upper coordinates
- self.x_u = []
- self.y_u = []
- # Lower coordinates
- self.x_l = []
- self.y_l = []
- # Upper coordinates
- self.x_u = []
- self.y_u = []
- # Lower coordinates
- self.x_l = []
- self.y_l = []
- # Coordinates x_u, y_u, x_l, y_l packed in single list
- self.coordinates = []
- global parent
- parent = self
-
- def create(self, chord, semi_span):
- self.chord = chord
- self.semi_span = semi_span
-
- chord = self.chord
- semi_span = self.semi_span
-
-
-class Airfoil(Coordinates):
- """This class enables the creation of a NACA airfoil."""
-
- def __init__(self):
- global parent
- # Run 'Coordinates' super class init method with same chord & 1/2 span.
- super().__init__(parent.chord, parent.semi_span)
- # NACA number
- self.naca_num = int()
- # Mean camber line
- self.x_c = []
- self.y_c = []
- # Thickness
- self.y_t = []
- # dy_c / d_x
- self.dy_c = []
- # Theta
- self.theta = []
-
- def naca(self, naca_num):
- """
- This function generates geometry for our chosen NACA airfoil shape.\
- The nested functions perform the required steps to generate geometry,\
- and can be called to solve the geometry y-coordinate for any 'x' input.\
- Equation coefficients were retrieved from Wikipedia.org.
-
- Parameters:
- naca_num: 4-digit NACA wing
- chord: wing chord length, in any unit
-
- Return:
- None
- """
-
- # Variables extracted from 'naca_num' argument passed to the function
- self.naca_num = naca_num
- m = int(str(naca_num)[0]) / 100
- p = int(str(naca_num)[1]) / 10
- t = int(str(naca_num)[2:]) / 100
- # Chord length. Should be higher than 10.
- if self.chord < 10:
- self.chord = 10
- # x-coordinate of maximum camber
- p_c = p * self.chord
-
- def get_camber(x):
- """
- Returns 1 camber y-coordinate from 1 'x' along the airfoil chord.
- """
- x_c = x
- y_c = float()
- if 0 <= x < p_c:
- y_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)
- + 2 * p * (x / self.chord)
- - (x / self.chord) ** 2)
- else:
- print('x-coordinate for camber is out of bounds. '
- 'Check that 0 < x <= chord.')
- return (x_c, y_c * self.chord)
-
- def get_thickness(x):
- """
- Returns thickness from 1 'x' along the airfoil chord.
- """
- y_t = float()
- if 0 <= x <= self.chord:
- y_t = 5 * t * self.chord * (0.2969 * sqrt(x / self.chord)
- - 0.1260 * (x / self.chord)
- - 0.3516 * (x / self.chord) ** 2
- + 0.2843 * (x / self.chord) ** 3
- - 0.1015 * (x / self.chord) ** 4)
- else:
- print('x-coordinate for thickness is out of bounds. '
- 'Check that 0 < x <= chord.')
- return y_t
-
- def get_dy_c(x):
- """
- Returns dy_c/dx from 1 'x' along the airfoil chord.
- """
- dy_c = float()
- if 0 <= x < p_c:
- dy_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)
- return dy_c
-
- def get_theta(dy_c):
- theta = atan(dy_c)
- return theta
-
- def get_upper_coordinates(x):
- x_u = float()
- y_u = float()
- if 0 <= x < self.chord:
- x_u = x - self.y_t[x] * sin(self.theta[x])
- y_u = self.y_c[x] + self.y_t[x] * cos(self.theta[x])
- elif x == self.chord:
- x_u = x - self.y_t[x] * sin(self.theta[x])
- y_u = 0 # Make upper curve finish at y = 0
- return(x_u, y_u)
-
- def get_lower_coordinates(x):
- x_l = float()
- y_l = float()
- if 0 <= x < self.chord:
- x_l = (x + self.y_t[x] * sin(self.theta[x]))
- y_l = (self.y_c[x] - self.y_t[x] * cos(self.theta[x]))
- elif x == self.chord:
- x_l = (x + self.y_t[x] * sin(self.theta[x]))
- y_l = 0 # Make lower curve finish at y = 0
- return(x_l, y_l)
-
- # Generate all our wing geometries from previous sub-functions
- for x in range(0, self.chord + 1):
- self.x_c.append(get_camber(x)[0])
- self.y_c.append(get_camber(x)[1])
- self.y_t.append(get_thickness(x))
- self.dy_c.append(get_dy_c(x))
- self.theta.append(get_theta(self.dy_c[x]))
- self.x_u.append(get_upper_coordinates(x)[0])
- self.y_u.append(get_upper_coordinates(x)[1])
- self.x_l.append(get_lower_coordinates(x)[0])
- self.y_l.append(get_lower_coordinates(x)[1])
-
- self.coordinates.append(self.x_u)
- self.coordinates.append(self.y_u)
- self.coordinates.append(self.x_l)
- self.coordinates.append(self.x_l)
-
- return None
-
- def print_geometry(self, round):
- """
- Print all the declared geometry to the terminal.
- """
- # Print all our basic geometry, useful for debugging
- print('Chord length')
- print(self.chord)
- print('x_c the x-coordinates of the mean camber line')
- print(np.around(self.x_c, round))
- print('y_c the y-coordinates of the mean camber line')
- print(np.around(self.y_c, round))
- print('y_t the y-coordinates of the airfoil thickness')
- print(np.around(self.y_t, round))
- print('dy_c the derivative of y_c with respect to dx')
- print(np.around(self.dy_c, round))
- print('theta is like an angle, idk')
- print(np.around(self.theta, round))
- print('x_u the x-coordinates of the upper airfoil surface')
- print(np.around(self.x_u, round))
- print('y_u the y-coordinates of the upper airfoil surface')
- print(np.around(self.y_u, round))
- print('x_l the x-coordinates of the lower airfoil surface')
- print(np.around(self.x_l, round))
- print('y_l the y-coordinates of lower airfoil surface')
- print(np.around(self.y_l, round))
- return None
-
- def save_values(self, airfoil_number, save_dir_path):
- """
- Save all the declared geometry to save_dir_path (must be full path).
- """
- file_name = 'airfoil_%s' % airfoil_number
- full_path = os.path.join(save_dir_path, file_name+'.txt')
- file = open(full_path, 'w')
- sys.stdout = file
- self.print_geometry(4)
- return None
-
-
-class Spar(Coordinates):
- """Contains a single spar's location and material."""
- global parent
-
- def __init__(self):
- super().__init__(parent.chord, parent.semi_span)
- # Spar material
- self.spar_material = []
-
- def add_spar(self, coordinates, material, spar_x):
- """
- Add a single spar at the % chord location given to function.
-
- Parameters:
- coordinates: provided by Airfoil.coordinates[x_u, y_u, x_l, y_l].
- material: spar's material. Assumes homogeneous material.
- spar_x: spar's location as a % of total chord length.
-
- Return:
- None
- """
- # Airfoil surface coordinates
- # unpacked from 'coordinates' (list of lists in 'Airfoil').
- x_u = coordinates[0]
- y_u = coordinates[1]
- x_l = coordinates[2]
- y_l = coordinates[3]
- # Scaled spar location with regards to chord
- loc = spar_x * self.chord
- # bisect_left: returns index of first value in x_u > loc.
- # This 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
- # These x and y coordinates are assigned to the spar, NOT airfoil.
- self.x_u.append(x_u[spar_x_u])
- self.y_u.append(y_u[spar_x_u])
- self.x_l.append(x_l[spar_x_l])
- self.y_l.append(y_l[spar_x_l])
- self.spar_material = material
- return None
-
-
-class Stringer():
- """Contains the coordinates of stringer(s) location and material."""
-
- def __init__(self):
- # Stringer attributes
- self.stringer_x_u = []
- self.stringer_y_u = []
- self.stringer_x_l = []
- self.stringer_y_l = []
- self.stringer_mat = []
-
- def add_stringers(self, material, *density):
- """
- Add stringers to the wing from their distribution density between spars.
- First half of density[] concerns stringer distribution on
-
- Parameters:
- material: stringer material
- *density:
-
- """
-
- # Find interval between leading edge and first upper stringer,
- # from density parameter den_u_1.
- interval = self.spar_x_u[0] / (den_u_1 * self.spar_x_u[0])
- # initialise first self.stringer_x_u at first interval.
- x = interval
- # Add upper stringers until first spar.
- while x < self.spar_x_u[0]:
- # Index of the first value of self.x_u > x
- x_u = bi.bisect_left(self.x_u, x)
- self.stringer_x_u.append(self.x_u[x_u])
- self.stringer_y_u.append(self.y_u[x_u])
- x += interval
-
- # Find interval between leading edge and first lower stringer,
- # from density parameter den_l_1.
- interval = self.spar_x_u[0] / (den_l_1 * self.spar_x_u[0])
- # initialise first self.stringer_x_l at first interval.
- x = interval
- # Add lower stringers until first spar.
- while x < self.spar_x_l[0]:
- # Index of the first value of self.x_l > x
- x_u = bi.bisect_left(self.x_l, x)
- self.stringer_x_l.append(self.x_l[x_u])
- self.stringer_y_l.append(self.y_l[x_u])
- x += interval
- return None
-
-
-def plot(airfoil, spar):
- """This function plots the elements passed as arguments."""
-
- print('Plotting airfoil.')
- # Plot chord
- x_chord = [0, airfoil.chord]
- y_chord = [0, 0]
- plt.plot(x_chord, y_chord, linewidth='1')
- # Plot mean camber line
- plt.plot(airfoil.x_c, airfoil.y_c, '-.', color='r', linewidth='2',
- label='mean camber line')
- # Plot upper surface
- plt.plot(airfoil.x_u, airfoil.y_u, '', color='b', linewidth='1')
- # Plot lower surface
- plt.plot(airfoil.x_l, airfoil.y_l, '', color='b', linewidth='1')
- # Plot spars
- try:
- for _ in range(0, len(spar.x_u)):
- x = (spar.spar_x_u[_], spar.spar_x_l[_])
- y = (spar.spar_y_u[_], spar.spar_y_l[_])
- plt.plot(x, y, '.-', color='b', label='spar')
- plt.legend()
- except:
- print('Did plot spars. Were they added?')
- # Plot stringers
- # if len(self.spar_x) != 0:
- # for _ in range(0, len(self.stringer_x)):
- # x = (self.stringer_x[_], self.stringer_x[_])
- # y = (self.stringer_y_u[_], self.stringer_y_l[_])
- # plt.scatter(x, y, color='y', linewidth='1',
- # else:
- # print('Unable to plot stringers. Were they created?')
- # Graph formatting
- plt.gcf().set_size_inches(9, 2.2)
- plt.xlabel('X axis')
- plt.ylabel('Y axis')
- # plt.gcf().set_size_inches(self.chord, max(self.y_u) - min(self.y_l))
- plt.grid(axis='both', linestyle=':', linewidth=1)
- plt.show()
- return None
-
-
-def main():
- return None
-
-
-if __name__ == '__main__':
- main()
Copyright 2019--2024 Marius PETER