summaryrefslogtreecommitdiff
path: root/evaluator.py
diff options
context:
space:
mode:
authorblendoit <blendoit@gmail.com>2019-10-20 19:33:53 -0700
committerblendoit <blendoit@gmail.com>2019-10-20 19:33:53 -0700
commit5e82dedea4c56eafc1bba4f3ec8677b15f51c03f (patch)
treed754b30ae1f7a892cd22ce092b5c1a8f5ebca847 /evaluator.py
parent87f2d5da23a0bb7159d64827390b5083b80f1375 (diff)
Commence declassification of Evaluator
Pointless to have a separate object for the Evaluator when a collection of evaluator.py methods does the trick.
Diffstat (limited to 'evaluator.py')
-rw-r--r--evaluator.py353
1 files changed, 0 insertions, 353 deletions
diff --git a/evaluator.py b/evaluator.py
deleted file mode 100644
index 2adc702..0000000
--- a/evaluator.py
+++ /dev/null
@@ -1,353 +0,0 @@
-"""
-The evaluator.py module contains a single Evaluator class,
-which knows all the attributes of a specified Aircraft instance,
-and contains functions to analyse the airfoil's geometrical
-& structural properties.
-"""
-
-import sys
-import os.path
-import numpy as np
-from math import sqrt
-import matplotlib.pyplot as plt
-import concurrent.futures
-import logging
-
-logging.basicConfig(filename='log_eval.txt',
- level=logging.DEBUG,
- format='%(asctime)s - %(levelname)s - %(message)s')
-
-
-class Evaluator:
- """Performs structural evaluations on aircrafts.
- Individual aircrafts must claim an Evaluator object as parent."""
- def __init__(self, name):
- self.name = name
- self.aircrafts = []
- self.results = []
-
- self.I_ = {'x': 0, 'z': 0, 'xz': 0}
-
- def _get_lift_rectangular(aircraft, lift=50):
- L_prime = np.array([
- lift / (aircraft.wing.semi_span * 2)
- for _ in range(aircraft.wing.semi_span)
- ])
- return L_prime
-
- def _get_lift_elliptical(aircraft, L_0=3.2):
- L_prime = np.array([
- 0.5 * L_0 / (aircraft.wing.semi_span * 2) *
- sqrt(1 - (y / aircraft.wing.semi_span)**2)
- for y in range(aircraft.wing.semi_span)
- ])
- return L_prime
-
- def get_lift_total(self, aircraft):
- """Combination of rectangular and elliptical lift."""
- # F_z = self._get_lift_rectangular(aircraft) + self._get_lift_elliptical(
- # aircraft)
- # F_z = self._get_lift_rectangular(
- # aircraft) + self._get_lift_elliptical(aircraft) / 2
- # F_z = [i + j for i, j in self._get_lift_rectangular]
- # return F_z
- return 420
-
- def get_mass_distribution(self, total_mass):
- F_z = [total_mass / self.semi_span for x in range(0, self.semi_span)]
- return F_z
-
- def get_mass_total(self, aircraft):
- """Get the total aircraft mass."""
- return 2000
-
- def get_drag(aircraft, drag):
- # Transform semi-span integer into list
- semi_span = [x for x in range(0, aircraft.wing.semi_span)]
-
- # Drag increases after 80% of the semi_span
- cutoff = round(0.8 * aircraft.wing.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 get_drag_total(self, aircraft):
- """Get total drag force acting on the aircraft."""
- return 500
-
- def get_centroid(aircraft):
- """Return the coordinates of the centroid."""
- stringer_area = aircraft.stringer.area
- cap_area = aircraft.spar.cap_area
-
- caps_x = [value for spar in aircraft.spar.x for value in spar]
- caps_z = [value for spar in aircraft.spar.z for value in spar]
- stringers_x = aircraft.stringer.x
- stringers_z = aircraft.stringer.z
-
- denominator = float(
- len(caps_x) * cap_area + len(stringers_x) * stringer_area)
-
- centroid_x = float(
- sum([x * cap_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 * cap_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."""
- stringer_area = self.stringer.area
- cap_area = self.spar.cap_area
-
- # Adds upper and lower components' coordinates to list
- 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]
- stringer_count = range(len(x_stringers))
- spar_count = range(len(self.spar.x))
-
- # I_x is the sum of the contributions of the spar caps and stringers
- # TODO: replace list indices with dictionary value
- I_x = sum([
- cap_area * (z_spars[i] - self.centroid[1])**2 for i in spar_count
- ])
- I_x += sum([
- stringer_area * (z_stringers[i] - self.centroid[1])**2
- for i in stringer_count
- ])
-
- I_z = sum([
- cap_area * (x_spars[i] - self.centroid[0])**2 for i in spar_count
- ])
- I_z += sum([
- stringer_area * (x_stringers[i] - self.centroid[0])**2
- for i in stringer_count
- ])
-
- I_xz = sum([
- cap_area * (x_spars[i] - self.centroid[0]) *
- (z_spars[i] - self.centroid[1]) for i in spar_count
- ])
- I_xz += sum([
- stringer_area * (x_stringers[i] - self.centroid[0]) *
- (z_stringers[i] - self.centroid[1]) for i in stringer_count
- ])
- return (I_x, I_z, I_xz)
-
- def get_dx(self, component):
- return [x - self.centroid[0] for x in component.x_start]
-
- def get_dz(self, component):
- return [x - self.centroid[1] for x in component.x_start]
-
- def get_dP(self, xDist, zDist, V_x, V_z, area):
- I_x = self.I_['x']
- I_z = self.I_['z']
- I_xz = self.I_['xz']
- denom = float(I_x * I_z - I_xz**2)
- z = float()
- for _ in range(len(xDist)):
- z += float(-area * xDist[_] * (I_x * V_x - I_xz * V_z) / denom -
- area * zDist[_] * (I_z * V_z - I_xz * V_x) / denom)
- return z
-
- def analyze(self, aircraft):
- """Analyze a single aircraft."""
- aircraft.results = {}
- aircraft.results.update({'Lift': self.get_lift_total(aircraft)})
- aircraft.results.update({'Drag': self.get_drag_total(aircraft)})
- aircraft.results.update({'Mass': self.get_mass_total(aircraft)})
- print(aircraft.results)
- return None
-
- def analyze_all(self):
- """Perform all analysis calculations on a all aircraft in evaluator."""
- with concurrent.futures.ProcessPoolExecutor() as executor:
- executor.map(self.analyze, self.aircrafts)
- return None
-
- # def analysis(self, V_x, V_z):
- # """Perform all analysis calculations and store in class instance."""
-
- # self.drag = self.get_drag(10)
- # self.lift_rectangular = self.get_lift_rectangular(13.7)
- # self.lift_elliptical = self.get_lift_elliptical(15)
- # self.lift_total = self.get_lift_total()
- # self.mass_dist = self.get_mass_distribution(self.mass_total)
- # self.centroid = self.get_centroid()
- # self.I_['x'] = self.get_inertia_terms()[0]
- # self.I_['z'] = self.get_inertia_terms()[1]
- # self.I_['xz'] = self.get_inertia_terms()[2]
- # spar_dx = self.get_dx(self.spar)
- # spar_dz = self.get_dz(self.spar)
- # self.spar.dP_x = self.get_dP(spar_dx, spar_dz, V_x, 0,
- # self.spar.cap_area)
- # self.spar.dP_z = self.get_dP(spar_dx, spar_dz, 0, V_z,
- # self.spar.cap_area)
- # print("yayyyyy")
- # return None
-
- # print(f"Analysis results for {aircraft.name}:\n", results)
- # self.results = self.get_lift_total(aircraft)
-
- # self.drag = self.get_drag(10)
- # self.lift_rectangular = self.get_lift_rectangular(13.7)
- # self.lift_elliptical = self.get_lift_elliptical(15)
- # self.lift_total = self.get_lift_total()
- # self.mass_dist = self.get_mass_distribution(self.mass_total)
- # self.centroid = self.get_centroid()
- # self.I_['x'] = self.get_inertia_terms()[0]
- # self.I_['z'] = self.get_inertia_terms()[1]
- # self.I_['xz'] = self.get_inertia_terms()[2]
- # spar_dx = self.get_dx(self.spar)
- # spar_dz = self.get_dz(self.spar)
- # self.spar.dP_x = self.get_dP(spar_dx, spar_dz, V_x, 0,
- # self.spar.cap_area)
- # self.spar.dP_z = self.get_dP(spar_dx, spar_dz, 0, V_z,
- # self.spar.cap_area)
- # return None
-
- def tree_print(self, *aircrafts):
- """Print the list of subcomponents."""
- name = f" TREE FOR {[i.name for i in aircrafts]} IN {self.name} "
- num_of_dashes = len(name)
- print(num_of_dashes * '-')
- print(name)
- for aircraft in aircrafts:
- print(".")
- print(f"`-- {aircraft}")
- print(f" |--{aircraft.wing}")
- print(f" | |-- {aircraft.wing.stringers}")
- for spar in aircraft.wing.spars[:-1]:
- print(f" | |-- {spar}")
- print(f" | `-- {aircraft.wing.spars[-1]}")
- print(f" |-- {aircraft.fuselage}")
- print(f" `-- {aircraft.propulsion}")
- print(num_of_dashes * '-')
- return None
-
- def tree_save(self,
- *aircrafts,
- save_path='/home/blendux/Projects/Aircraft_Studio/save'):
- """Save the evaluator's tree to a file."""
- for aircraft in aircrafts:
- file_name = f"{aircraft.name}_tree.txt"
- full_path = os.path.join(save_path, file_name)
- with open(full_path, 'w') as f:
- try:
- f.write(".\n")
- f.write(f"`-- {aircraft}\n")
- f.write(f" |--{aircraft.wing}\n")
- for spar in aircraft.wing.spars[:-1]:
- f.write(f" | |-- {spar}\n")
- f.write(f" | `-- {aircraft.wing.spars[-1]}\n")
- f.write(f" |-- {aircraft.fuselage}\n")
- f.write(f" `-- {aircraft.propulsion}\n")
- logging.debug(f'Successfully wrote to file {full_path}')
-
- except IOError:
- print(
- f'Unable to write {file_name} to specified directory.',
- 'Was the full path passed to the function?')
- return None
-
- def info_save(self, save_path, number):
- """Save all the object's coordinates (must be full path)."""
- file_name = 'airfoil_{}_eval.txt'.format(number)
- full_path = os.path.join(save_path, file_name)
- try:
- with open(full_path, 'w') as sys.stdout:
- self.info_print(6)
- # 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 plot_geom(evaluator):
- """This function plots analysis results over the airfoil's geometry."""
- # Plot chord
- x_chord = [0, evaluator.chord]
- y_chord = [0, 0]
- plt.plot(x_chord, y_chord, linewidth='1')
- # Plot quarter chord
- plt.plot(evaluator.chord / 4,
- 0,
- '.',
- color='g',
- markersize=24,
- label='Quarter-chord')
- # Plot airfoil surfaces
- x = [0.98 * x for x in evaluator.airfoil.x]
- y = [0.98 * z for z in evaluator.airfoil.z]
- plt.fill(x, y, color='w', linewidth='1', fill=False)
- x = [1.02 * x for x in evaluator.airfoil.x]
- y = [1.02 * z for z in evaluator.airfoil.z]
- plt.fill(x, y, color='b', linewidth='1', fill=False)
-
- # Plot spars
- 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 stringers
- 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 centroid
- x = evaluator.centroid[0]
- y = evaluator.centroid[1]
- plt.plot(x, y, '.', color='r', markersize=24, label='centroid')
-
- # Graph formatting
- plt.xlabel('X axis')
- plt.ylabel('Z axis')
-
- plot_bound = max(evaluator.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)
- plt.show()
- return None
-
-
-def plot_lift(evaluator):
- x = range(evaluator.semi_span)
- y_1 = evaluator.lift_rectangular
- y_2 = evaluator.lift_elliptical
- y_3 = evaluator.lift_total
- plt.plot(x, y_1, '.', color='b', markersize=4, label='Rectangular lift')
- plt.plot(x, y_2, '.', color='g', markersize=4, label='Elliptical lift')
- plt.plot(x, y_3, '.', color='r', markersize=4, label='Total lift')
-
- # Graph formatting
- plt.xlabel('Semi-span location')
- plt.ylabel('Lift')
-
- plt.gca().legend()
- plt.grid(axis='both', linestyle=':', linewidth=1)
- plt.show()
- return None
Copyright 2019--2024 Marius PETER