diff options
-rw-r--r-- | creator.py | 1 | ||||
-rw-r--r-- | evaluator.py | 171 | ||||
-rw-r--r-- | main.py | 21 |
3 files changed, 125 insertions, 68 deletions
@@ -75,6 +75,7 @@ class Coordinates: This function's output is piped to the 'save_coord' function below. """ print('============================') + print(' CREATOR DATA ') print('Component:', str(self)) print('Chord length:', self.chord) print('Semi-span:', self.semi_span) diff --git a/evaluator.py b/evaluator.py index 2b61348..6965895 100644 --- a/evaluator.py +++ b/evaluator.py @@ -13,60 +13,129 @@ # 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, atan, sqrt -def get_total_mass(*component): - total_mass = float() - for _ in component: - total_mass += _.mass - return total_mass +class Airfoil: + '''Performs structural evaluations for the airfoil passed as argument.''' + + def __init__(self, airfoil): + self.airfoil = airfoil + # Global dimensions + self.chord = airfoil.chord + self.semi_span = airfoil.semi_span + # mass and area + self.mass_total = float() + self.mass_dist = [] + + self.lift_rectangular = [] + self.lift_elliptical = [] + self.lift = [] + + self.drag = [] + + def __str__(self): + return type(self).__name__ + + def print_info(self, round): + """ + Print all the component's evaluated data to the terminal. + + This function's output is piped to the 'save_data' function below. + """ + print('============================') + print(' EVALUATOR DATA ') + print('Evaluating:', str(self.airfoil)) + print('Chord length:', self.chord) + print('Semi-span:', self.semi_span) + print('Total airfoil mass:', self.mass_total) + print('============================') + print('Rectangular lift:\n', np.around(self.lift_rectangular, round)) + print('Elliptical lift:\n', np.around(self.lift_elliptical, round)) + print('Combined lift:\n', np.around(self.lift, round)) + print('Distribution of mass:\n', np.around(self.mass_dist, round)) + print('Drag:\n', np.around(self.drag, round)) + return None + + def save_info(self, save_dir_path, number): + """ + Save all the object's coordinates (must be full path). + """ + + file_name = '{}_{}.txt'.format(self, number) + full_path = os.path.join(save_dir_path, file_name) + try: + with open(full_path, 'w') as sys.stdout: + self.print_info(2) + # This line required to reset behavior of sys.stdout + sys.stdout = sys.__stdout__ + print('Successfully wrote to file {}'.format(full_path)) + except IOError: + print('Unable to write {} to specified directory.\n' + .format(file_name), + 'Was the full path passed to the function?') + return None + + def get_mass_total(airfoil): + total_mass = airfoil.mass + airfoil.spar.mass + airfoil.stringer.mass + return total_mass + + # All these functions take integer arguments and return lists. + + def get_lift_rectangular(airfoil, lift): + L_prime = [lift / (airfoil.semi_span * 2) + for x in range(airfoil.semi_span)] + return L_prime + + def get_lift_elliptical(airfoil, L_0): + L_prime = [L_0 * sqrt(1 - (y / airfoil.semi_span) ** 2) + for y in range(airfoil.semi_span)] + return L_prime + + def get_lift(rectangular, elliptical): + F_z = [(rectangular[_] + elliptical[_]) / 2 + for _ in range(len(rectangular))] + return F_z + + def get_mass_distribution(airfoil, total_mass): + F_z = [total_mass / airfoil.semi_span + for x in range(0, airfoil.semi_span)] + return F_z + + def get_drag(airfoil, drag): + # Transform semi-span integer into list + semi_span = [x for x in range(0, airfoil.semi_span)] + + # Drag increases after 80% of the semi_span + cutoff = round(0.8 * airfoil.semi_span) + + # Drag increases by 25% after 80% of the semi_span + F_x = [drag for x in semi_span[0:cutoff]] + F_x.extend([1.25 * drag for x in semi_span[cutoff:]]) + return F_x + + def evaluate(self): + self.drag = self.get_drag(self.airfoil, 10) + + self.lift_rectangular = self.get_lift_rectangular(10) + self.lift_elliptical = self.get_lift_elliptical(15) + self.lift = self.get_lift(self.lift_rectangular, self.lift_elliptical) + + self.mass_total = self.get_mass_total() + self.mass_dist = self.get_mass_distribution(self.total_mass) + return None + +# def get_centroid(airfoil): +# area = airfoil.stringer.area +# top_stringers = airfoil.stringer +# bottom_stringers = +# nose_top_stringers = +# nose_bottom_stringers = +# for _ in airfoil.stringer[1]: +# centroid.x += - -# All these functions take integer arguments and return lists. - -def get_lift_rectangular(airfoil, lift): - L_prime = [lift / (airfoil.semi_span * 2) - for x in range(airfoil.semi_span)] - return L_prime - - -def get_lift_elliptical(airfoil, L_0): - L_prime = [L_0 * sqrt(1 - (y / airfoil.semi_span) ** 2) - for y in range(airfoil.semi_span)] - return L_prime - - -def get_lift(rectangular, elliptical): - F_z = [(rectangular[_] + elliptical[_]) / 2 - for _ in range(len(rectangular))] - return F_z - - -def get_mass_distribution(airfoil, total_mass): - F_z = [total_mass / airfoil.semi_span - for x in range(0, airfoil.semi_span)] - return F_z - - -def get_drag(airfoil, drag): - # Transform semi-span integer into list - semi_span = [x for x in range(0, airfoil.semi_span)] - cutoff = round(0.8 * airfoil.semi_span) - - F_x = [drag for x in semi_span[0:cutoff]] - F_x.extend([1.25 * drag for x in semi_span[cutoff:]]) - # for x in semi_span[cutoff:]: - # drag_distribution.append(1.25 * drag) - return F_x - - -def get_centroid(airfoil): - area = airfoil.stringer.area - numerator = float() - for _ in airfoil.stringer.x_u: - numerator += _ * area - for _ in airfoil.stringer.x_l: - numerator += _ * area # denominator # z_c = @@ -76,21 +76,6 @@ def main(): af.stringer.add_mass(STRINGER_MASS) # af.stringer.print_info(2) - # print(evaluator.get_total_mass(af, af.spar, af.stringer)) - drag = evaluator.get_drag(af, 10) - - lift_rectangular = evaluator.get_lift_rectangular(af, 10) - lift_elliptical = evaluator.get_lift_elliptical(af, 15) - lift = evaluator.get_lift(lift_rectangular, lift_elliptical) - - total_mass = evaluator.get_total_mass(af, af.spar, af.stringer) - dist_mass = evaluator.get_mass_distribution(af, total_mass) - print('rect', len(lift_rectangular)) - print('ellipse', len(lift_elliptical)) - print('lift', len(lift)) - print(len(drag)) - print(len(dist_mass)) - # Plot components with matplotlib # creator.plot(af, af.spar, af.stringer) @@ -99,8 +84,10 @@ def main(): # af.spar.save_info(SAVE_PATH, _) # af.stringer.save_info(SAVE_PATH, _) - # Evaluate previously created airfoil(s). - # total_mass = evaluator.get_total_mass(af, af.spar, af.stringer) + # evaluator.Airfoil instance contains the results of the airfoil analysis. + # The analysis itself takes place in the evaluator.py module. + eval = evaluator.Airfoil(af) + eval.print_info(2) # Print final execution time print("--- %s seconds ---" % (time.time() - start_time)) |