evaluator.Airfoil class & class methods

Commit
43d8b1a738eef259063febd9e5c591a10610a043
Author
Marius Peter <blendoit@gmail.com>
Author date
Committer
Marius Peter <blendoit@gmail.com>
Committer date
Changed files
creator.py
index 07720e8f..15c090f7 100644..100644
@@ -75,6 +75,7 @@
75 75 This function's output is piped to the 'save_coord' function below.
76 76 """
77 77 print('============================')
78 Added: print(' CREATOR DATA ')
78 79 print('Component:', str(self))
79 80 print('Chord length:', self.chord)
80 81 print('Semi-span:', self.semi_span)
evaluator.py
index 2b61348c..6965895b 100644..100644
@@ -13,60 +13,129 @@
13 13 # You should have received a copy of the GNU General Public License
14 14 # along with this program. If not, see <https://www.gnu.org/licenses/>.
15 15
16 Added: import sys
17 Added: import os.path
18 Added: import numpy as np
16 19 from math import sin, cos, atan, sqrt
17 20
18 21
19 Removed: def get_total_mass(*component):
20 Removed: total_mass = float()
21 Removed: for _ in component:
22 Removed: total_mass += _.mass
23 Removed: return total_mass
22 Added: class Airfoil:
23 Added: '''Performs structural evaluations for the airfoil passed as argument.'''
24 24
25 Added: def __init__(self, airfoil):
26 Added: self.airfoil = airfoil
27 Added: # Global dimensions
28 Added: self.chord = airfoil.chord
29 Added: self.semi_span = airfoil.semi_span
30 Added: # mass and area
31 Added: self.mass_total = float()
32 Added: self.mass_dist = []
25 33
26 Removed: # All these functions take integer arguments and return lists.
34 Added: self.lift_rectangular = []
35 Added: self.lift_elliptical = []
36 Added: self.lift = []
27 37
28 Removed: def get_lift_rectangular(airfoil, lift):
29 Removed: L_prime = [lift / (airfoil.semi_span * 2)
30 Removed: for x in range(airfoil.semi_span)]
31 Removed: return L_prime
38 Added: self.drag = []
32 39
40 Added: def __str__(self):
41 Added: return type(self).__name__
33 42
34 Removed: def get_lift_elliptical(airfoil, L_0):
35 Removed: L_prime = [L_0 * sqrt(1 - (y / airfoil.semi_span) ** 2)
36 Removed: for y in range(airfoil.semi_span)]
37 Removed: return L_prime
43 Added: def print_info(self, round):
44 Added: """
45 Added: Print all the component's evaluated data to the terminal.
38 46
47 Added: This function's output is piped to the 'save_data' function below.
48 Added: """
49 Added: print('============================')
50 Added: print(' EVALUATOR DATA ')
51 Added: print('Evaluating:', str(self.airfoil))
52 Added: print('Chord length:', self.chord)
53 Added: print('Semi-span:', self.semi_span)
54 Added: print('Total airfoil mass:', self.mass_total)
55 Added: print('============================')
56 Added: print('Rectangular lift:\n', np.around(self.lift_rectangular, round))
57 Added: print('Elliptical lift:\n', np.around(self.lift_elliptical, round))
58 Added: print('Combined lift:\n', np.around(self.lift, round))
59 Added: print('Distribution of mass:\n', np.around(self.mass_dist, round))
60 Added: print('Drag:\n', np.around(self.drag, round))
61 Added: return None
39 62
40 Removed: def get_lift(rectangular, elliptical):
41 Removed: F_z = [(rectangular[_] + elliptical[_]) / 2
42 Removed: for _ in range(len(rectangular))]
43 Removed: return F_z
63 Added: def save_info(self, save_dir_path, number):
64 Added: """
65 Added: Save all the object's coordinates (must be full path).
66 Added: """
44 67
68 Added: file_name = '{}_{}.txt'.format(self, number)
69 Added: full_path = os.path.join(save_dir_path, file_name)
70 Added: try:
71 Added: with open(full_path, 'w') as sys.stdout:
72 Added: self.print_info(2)
73 Added: # This line required to reset behavior of sys.stdout
74 Added: sys.stdout = sys.__stdout__
75 Added: print('Successfully wrote to file {}'.format(full_path))
76 Added: except IOError:
77 Added: print('Unable to write {} to specified directory.\n'
78 Added: .format(file_name),
79 Added: 'Was the full path passed to the function?')
80 Added: return None
45 81
46 Removed: def get_mass_distribution(airfoil, total_mass):
47 Removed: F_z = [total_mass / airfoil.semi_span
48 Removed: for x in range(0, airfoil.semi_span)]
49 Removed: return F_z
82 Added: def get_mass_total(airfoil):
83 Added: total_mass = airfoil.mass + airfoil.spar.mass + airfoil.stringer.mass
84 Added: return total_mass
50 85
86 Added: # All these functions take integer arguments and return lists.
51 87
52 Removed: def get_drag(airfoil, drag):
53 Removed: # Transform semi-span integer into list
54 Removed: semi_span = [x for x in range(0, airfoil.semi_span)]
55 Removed: cutoff = round(0.8 * airfoil.semi_span)
88 Added: def get_lift_rectangular(airfoil, lift):
89 Added: L_prime = [lift / (airfoil.semi_span * 2)
90 Added: for x in range(airfoil.semi_span)]
91 Added: return L_prime
56 92
57 Removed: F_x = [drag for x in semi_span[0:cutoff]]
58 Removed: F_x.extend([1.25 * drag for x in semi_span[cutoff:]])
59 Removed: # for x in semi_span[cutoff:]:
60 Removed: # drag_distribution.append(1.25 * drag)
61 Removed: return F_x
93 Added: def get_lift_elliptical(airfoil, L_0):
94 Added: L_prime = [L_0 * sqrt(1 - (y / airfoil.semi_span) ** 2)
95 Added: for y in range(airfoil.semi_span)]
96 Added: return L_prime
62 97
98 Added: def get_lift(rectangular, elliptical):
99 Added: F_z = [(rectangular[_] + elliptical[_]) / 2
100 Added: for _ in range(len(rectangular))]
101 Added: return F_z
63 102
64 Removed: def get_centroid(airfoil):
65 Removed: area = airfoil.stringer.area
66 Removed: numerator = float()
67 Removed: for _ in airfoil.stringer.x_u:
68 Removed: numerator += _ * area
69 Removed: for _ in airfoil.stringer.x_l:
70 Removed: numerator += _ * area
103 Added: def get_mass_distribution(airfoil, total_mass):
104 Added: F_z = [total_mass / airfoil.semi_span
105 Added: for x in range(0, airfoil.semi_span)]
106 Added: return F_z
107 Added:
108 Added: def get_drag(airfoil, drag):
109 Added: # Transform semi-span integer into list
110 Added: semi_span = [x for x in range(0, airfoil.semi_span)]
111 Added:
112 Added: # Drag increases after 80% of the semi_span
113 Added: cutoff = round(0.8 * airfoil.semi_span)
114 Added:
115 Added: # Drag increases by 25% after 80% of the semi_span
116 Added: F_x = [drag for x in semi_span[0:cutoff]]
117 Added: F_x.extend([1.25 * drag for x in semi_span[cutoff:]])
118 Added: return F_x
119 Added:
120 Added: def evaluate(self):
121 Added: self.drag = self.get_drag(self.airfoil, 10)
122 Added:
123 Added: self.lift_rectangular = self.get_lift_rectangular(10)
124 Added: self.lift_elliptical = self.get_lift_elliptical(15)
125 Added: self.lift = self.get_lift(self.lift_rectangular, self.lift_elliptical)
126 Added:
127 Added: self.mass_total = self.get_mass_total()
128 Added: self.mass_dist = self.get_mass_distribution(self.total_mass)
129 Added: return None
130 Added:
131 Added: # def get_centroid(airfoil):
132 Added: # area = airfoil.stringer.area
133 Added: # top_stringers = airfoil.stringer
134 Added: # bottom_stringers =
135 Added: # nose_top_stringers =
136 Added: # nose_bottom_stringers =
137 Added: # for _ in airfoil.stringer[1]:
138 Added: # centroid.x +=
139 Added:
71 140 # denominator
72 141 # z_c =
main.py
index a23c3f00..e5360ff2 100644..100644
@@ -76,21 +76,6 @@
76 76 af.stringer.add_mass(STRINGER_MASS)
77 77 # af.stringer.print_info(2)
78 78
79 Removed: # print(evaluator.get_total_mass(af, af.spar, af.stringer))
80 Removed: drag = evaluator.get_drag(af, 10)
81 Removed:
82 Removed: lift_rectangular = evaluator.get_lift_rectangular(af, 10)
83 Removed: lift_elliptical = evaluator.get_lift_elliptical(af, 15)
84 Removed: lift = evaluator.get_lift(lift_rectangular, lift_elliptical)
85 Removed:
86 Removed: total_mass = evaluator.get_total_mass(af, af.spar, af.stringer)
87 Removed: dist_mass = evaluator.get_mass_distribution(af, total_mass)
88 Removed: print('rect', len(lift_rectangular))
89 Removed: print('ellipse', len(lift_elliptical))
90 Removed: print('lift', len(lift))
91 Removed: print(len(drag))
92 Removed: print(len(dist_mass))
93 Removed:
94 79 # Plot components with matplotlib
95 80 # creator.plot(af, af.spar, af.stringer)
96 81
@@ -99,8 +84,10 @@
99 84 # af.spar.save_info(SAVE_PATH, _)
100 85 # af.stringer.save_info(SAVE_PATH, _)
101 86
102 Removed: # Evaluate previously created airfoil(s).
103 Removed: # total_mass = evaluator.get_total_mass(af, af.spar, af.stringer)
87 Added: # evaluator.Airfoil instance contains the results of the airfoil analysis.
88 Added: # The analysis itself takes place in the evaluator.py module.
89 Added: eval = evaluator.Airfoil(af)
90 Added: eval.print_info(2)
104 91
105 92 # Print final execution time
106 93 print("--- %s seconds ---" % (time.time() - start_time))