Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
# Rotate the mean camber line (MCL) and "upper minus mcl"
new_mcl_coordinates_after = np.transpose(
rotation_matrix @ np.transpose(mcl_coordinates_after - hinge_point)) + hinge_point
new_upper_minus_mcl_after = np.transpose(rotation_matrix @ np.transpose(upper_minus_mcl_after))
# Do blending
# Assemble airfoil
new_mcl_coordinates = np.vstack((mcl_coordinates_before, new_mcl_coordinates_after))
new_upper_minus_mcl = np.vstack((upper_minus_mcl_before, new_upper_minus_mcl_after))
upper_coordinates = np.flipud(new_mcl_coordinates + new_upper_minus_mcl)
lower_coordinates = new_mcl_coordinates - new_upper_minus_mcl
coordinates = np.vstack((upper_coordinates, lower_coordinates[1:, :]))
new_airfoil = Airfoil(name=self.name + " flapped", coordinates=coordinates, repanel=False)
return new_airfoil # TODO fix self-intersecting airfoils at high deflections
# Do the contraction
upper_minus_mcl_adjusted = self.upper_minus_mcl - self.upper_minus_mcl[-1, :] * np.expand_dims(scale_factor, 1)
# Recreate coordinates
upper_coordinates_adjusted = np.flipud(self.mcl_coordinates + upper_minus_mcl_adjusted)
lower_coordinates_adjusted = self.mcl_coordinates - upper_minus_mcl_adjusted
coordinates = np.vstack((
upper_coordinates_adjusted[:-1, :],
lower_coordinates_adjusted
))
# Make a new airfoil with the coordinates
name = self.name + ", with sharp TE"
new_airfoil = Airfoil(name=name, coordinates=coordinates, repanel=False)
return new_airfoil
# Generate a cosine-spaced list of points from 0 to 1
s = cosspace(n_points=n_points_per_side)
x_upper_func = sp_interp.PchipInterpolator(x=upper_distances_from_TE_normalized, y=upper_original_coors[:, 0])
y_upper_func = sp_interp.PchipInterpolator(x=upper_distances_from_TE_normalized, y=upper_original_coors[:, 1])
x_lower_func = sp_interp.PchipInterpolator(x=lower_distances_from_LE_normalized, y=lower_original_coors[:, 0])
y_lower_func = sp_interp.PchipInterpolator(x=lower_distances_from_LE_normalized, y=lower_original_coors[:, 1])
x_coors = np.hstack((x_upper_func(s), x_lower_func(s)[1:]))
y_coors = np.hstack((y_upper_func(s), y_lower_func(s)[1:]))
coordinates = np.column_stack((x_coors, y_coors))
# Make a new airfoil with the coordinates
name = self.name + ", repaneled to " + str(n_points_per_side) + " pts"
new_airfoil = Airfoil(name=name, coordinates=coordinates, repanel=False)
return new_airfoil
foil1 = copy.deepcopy(airfoil1)
foil2 = copy.deepcopy(airfoil2)
if blend_fraction == 0:
return foil1
if blend_fraction == 1:
return foil2
assert blend_fraction >= 0 and blend_fraction <= 1, "blend_fraction is out of the valid range of 0 to 1!"
# Repanel to ensure the same number of points and the same point distribution on both airfoils.
foil1 = foil1.get_repaneled_airfoil(n_points_per_side=200)
foil2 = foil2.get_repaneled_airfoil(n_points_per_side=200)
blended_coordinates = (1 - blend_fraction) * foil1.coordinates + blend_fraction * foil2.coordinates
new_airfoil = Airfoil(name="Blended Airfoils", coordinates=blended_coordinates)
return new_airfoil
profiler.dump_stats(filename)
# profiler.print_stats()
return wrapper
class AeroProblem:
def __init__(self,
airplane, # Object of Airplane class
op_point, # Object of OperatingPoint class
):
self.airplane = airplane
self.op_point = op_point
class vlm1(AeroProblem):
# NOTE: USE VLM2 INSTEAD OF THIS; VLM1 HAS BEEN COMPLETELY SUPERSEDED IN PERFORMANCE AND FUNCTIONALITY BY VLM2.
# Traditional vortex-lattice-method approach with quadrilateral paneling, horseshoe vortices from each one, etc.
# Implemented exactly as The Good Book says (Drela, "Flight Vehicle Aerodynamics", p. 130-135)
@profile
def run(self, verbose=True):
self.verbose = verbose
if self.verbose: print("Running VLM1 calculation...")
# Deprecation warning (use VLM2 instead)
if self.verbose: print("WARNING! VLM1 has been wholly eclipsed in performance and functionality by VLM2. The VLM1 source code has been left intact for validation purposes and backwards-compatibility, but it will not be supported going forward.")
self.make_panels()
self.setup_geometry()
self.setup_operating_point()
ax.text(
panel.colocation_point[0],
panel.colocation_point[1],
panel.colocation_point[2],
str(panel_num),
)
x, y, z, s = self.airplane.get_bounding_cube()
ax.set_xlim3d((x - s, x + s))
ax.set_ylim3d((y - s, y + s))
ax.set_zlim3d((z - s, z + s))
plt.tight_layout()
plt.show()
class vlm2(AeroProblem):
# Vortex-Lattice Method aerodynamics code written from the ground up with lessons learned from writing VLM1.
# Should eventually eclipse VLM1 in performance and render it obsolete.
#
# Notable improvements over VLM1:
# # Specifically written to be reverse-mode-AD-compatible at every step
# # Supports control surfaces
# # Supports bodies in quasi-steady rotation (nonzero p, q, and r)
# # Supports calculation of stability derivatives
# # Vortex lattice follows the mean camber line for higher accuracy (though control deflections are done by rotating normals)
# # TODO: Takes advantage of the connectivity of the vortex lattice to speed up calculate_Vij() by almost exactly 2x
# # TODO: calculate_Vij() is parallelized, one core per wing
#
# Usage:
# # Set up a problem using the syntax in the AeroProblem constructor (e.g. "vlm2(airplane = a, op_point = op)" for some Airplane a and OperatingPoint op)
# # Call vlm2.run() to run the problem.
# # Access results in the command line, or through properties of the vlm2 class.
x = np.hstack((x_U, x_L))
y = np.hstack((y_U, y_L))
coordinates = np.column_stack((x, y))
self.coordinates = coordinates
return
else:
print("Unfortunately, only 4-series NACA airfoils can be generated at this time.")
# Try to read from airfoil database
try:
import importlib.resources
from . import airfoils
raw_text = importlib.resources.read_text(airfoils, name + '.dat')
trimmed_text = raw_text[raw_text.find('\n'):]
coordinates1D = np.fromstring(trimmed_text, sep='\n') # returns the coordinates in a 1D array
assert len(
coordinates1D) % 2 == 0, 'File was found in airfoil database, but it could not be read correctly!' # Should be even
coordinates = np.reshape(coordinates1D, (-1, 2))
self.coordinates = coordinates
return
except FileNotFoundError:
print("File was not found in airfoil database!")