Skip to content

Commit

Permalink
I prepped geometry and meshing to transition to defining the WingCros…
Browse files Browse the repository at this point in the history
…sSection objects with respect to the Wing frame.
  • Loading branch information
camUrban committed Dec 5, 2024
1 parent 4a67fa8 commit 2f71842
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 45 deletions.
106 changes: 61 additions & 45 deletions pterasoftware/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,24 +65,27 @@ def __init__(
:param name: str, optional
A sensible name for your airplane. The default is "Untitled Airplane".
:param x_ref: float, optional
This is the x coordinate of the moment reference point. It should be the
x coordinate of the center of gravity. The default is 0.0.
This is the x coordinate of the moment reference point in the body
frame. It should be the x coordinate of the center of gravity. The
default is 0.0.
:param y_ref: float, optional
This is the y coordinate of the moment reference point. It should be the
y coordinate of the center of gravity. The default is 0.0.
This is the y coordinate of the moment reference point in the body
frame. It should be the y coordinate of the center of gravity. The
default is 0.0.
:param z_ref: float, optional
This is the z coordinate of the moment reference point. It should be the
z coordinate of the center of gravity. The default is 0.0.
This is the z coordinate of the moment reference point in the body
frame. It should be the z coordinate of the center of gravity. The
default is 0.0.
:param weight: float, optional
This parameter holds the weight of the aircraft in Newtons. This is used
by the trim functions. The default value is 0.0.
:param s_ref: float, optional if more than one wing is in the wings list.
:param s_ref: float, optional
This is the reference wetted area. If not set, it populates from first
wing object.
:param c_ref: float, optional if more than one wing is in the wings list.
:param c_ref: float, optional
This is the reference chord length. If not set, it populates from first
wing object.
:param b_ref: float, optional if more than one wing is in the wings list.
:param b_ref: float
This is the reference calculate_span. If not set, it populates from first
wing object.
"""
Expand All @@ -92,14 +95,16 @@ def __init__(
else:
raise Exception("An airplane's list of wings must have at least one entry.")

# Initialize the name, moment reference point coordinates, and weight.
# Initialize the name, moment reference point coordinates (in the body frame),
# and weight.
self.name = name
self.x_ref = x_ref
self.y_ref = y_ref
self.z_ref = z_ref
self.weight = weight

# Create a (3,) array to hold the moment reference point coordinates.
# Create a (3,) array to hold the moment reference point coordinates in the
# body frame.
self.xyz_ref = np.array([self.x_ref, self.y_ref, self.z_ref])

# Set the wing reference dimensions to be the main wing's reference dimensions.
Expand Down Expand Up @@ -205,34 +210,33 @@ def __init__(
:param name: str, optional
This is a sensible name for the wing. The default is "Untitled Wing".
:param x_le: float, optional
This is the x coordinate of the leading edge of the wing, relative to the
airplane's reference point. The default is 0.0.
This is the x coordinate of the leading edge of the wing in the body
frame. The default is 0.0.
:param y_le: float, optional
This is the y coordinate of the leading edge of the wing, relative to the
airplane's reference point. The default is 0.0.
This is the y coordinate of the leading edge of the wing in the body
frame. The default is 0.0.
:param z_le: float, optional
This is the z coordinate of the leading edge of the wing, relative to the
airplane's reference point. The default is 0.0.
:param unit_normal_vector: array, optional
This is an (3,) array of floats that represents the unit normal vector
of the wing's symmetry plane. It is also the direction vector that the
wing's span will be assessed relative to. Additionally, this vector
crossed with the "unit_chordwise_vector" defines the normal vector of the
plane that the wing's projected area will reference. It must be
equivalent to this wing's root wing cross section's "unit_normal_vector"
attribute. The default is np.array([0.0, 1.0, 0.0]), which is the XZ
plane's unit normal vector.
This is the z coordinate of the leading edge of the wing in the body
frame. The default is 0.0.
:param unit_normal_vector: (3,) array of floats, optional
This is an (3,) array of floats that represents the unit normal vector of
the wing's symmetry plane in the body frame. It is also the direction
vector that the wing's span will be assessed relative to. Additionally,
this vector crossed with the "unit_chordwise_vector" defines the normal
vector of the plane that the wing's projected area will reference. It
must be equivalent to this wing's root wing cross section's
"unit_normal_vector" attribute. The default is np.array([0.0, 1.0, 0.0]),
which is the XZ body frame's unit normal vector.
:param symmetric: bool, optional
Set this to true if the wing is across the xz plane. Set it to false if
not. The default is false.
:param unit_chordwise_vector: array, optional
Set this to true if the wing is symmetric across the plane defined by its
unit normal vector. Set it to false if not. The default is false.
:param unit_chordwise_vector: (3,) array of floats, optional
This is an (3,) array of floats that represents the unit vector that
defines the wing's chordwise direction. This vector crossed with the
"unit_normal_vector" defines the normal vector of the plane that
the wing's projected area will reference. This vector must be parallel to
the intersection of the wing's symmetry plane with each of its wing cross
section's planes. The default is np.array([1.0, 0.0, 0.0]), which is the
X unit vector.
defines the wing's chordwise direction in the body frame. This vector
crossed with the "unit_normal_vector" defines the normal vector of the
plane that the wing's projected area will reference. This vector must be
parallel to the intersection of the wing's symmetry plane with each of
its wing cross section's planes. The default is np.array([1.0, 0.0, 0.0]).
:param num_chordwise_panels: int, optional
This is the number of chordwise panels to be used on this wing. The
default is 8.
Expand All @@ -252,7 +256,8 @@ def __init__(
"two entries."
)

# Initialize the name and the position of the wing's leading edge.
# Initialize the name and the position of the wing's leading edge in the body
# frame.
self.name = name
self.x_le = x_le
self.y_le = y_le
Expand All @@ -269,11 +274,14 @@ def __init__(
else:
raise Exception('The chordwise spacing must be "cosine" or "uniform".')

# Create a (3,) array to hold the leading edge's coordinates.
# Create a (3,) array to hold the wing's leading edge's coordinates in the
# body frame.
self.leading_edge = np.array([self.x_le, self.y_le, self.z_le])

# Check that the wing's symmetry plane is equal to its root wing cross
# section's plane.
# ToDo: Modify this check once the wing cross section vectors reference the
# wing's frame.
# Check that the wing's symmetry plane in the body frame is equal to its root
# wing cross section's plane.
if not np.array_equal(
self.unit_normal_vector,
self.wing_cross_sections[0].unit_normal_vector,
Expand All @@ -283,6 +291,8 @@ def __init__(
"section's plane."
)

# ToDo: Modify this check once the wing cross section coordinates reference the
# wing's frame.
# Check that the root wing cross section's leading edge isn't offset from the
# wing's leading edge.
if np.any(
Expand All @@ -299,7 +309,8 @@ def __init__(
"the wing's leading edge."
)

# Check that the wing's chordwise and normal directions are perpendicular.
# Check that the wing's body-frame chordwise and normal directions are
# perpendicular.
if np.dot(self.unit_chordwise_vector, self.unit_normal_vector) != 0:
raise Exception(
"Every wing cross section's plane must intersect with the wing's "
Expand All @@ -317,6 +328,8 @@ def __init__(
if self.symmetric:
self.num_spanwise_panels *= 2

# ToDo: Modify this check once the wing cross section vectors reference the
# wing's frame.
# Check that all the wing cross sections have valid unit normal vectors.
for wing_cross_section in self.wing_cross_sections:

Expand All @@ -338,6 +351,8 @@ def __init__(
# Calculate the number of panels on this wing.
self.num_panels = self.num_spanwise_panels * self.num_chordwise_panels

# ToDo: Determine if this is still necessary once the wing cross section
# vectors reference the wing's frame.
for wing_cross_section in self.wing_cross_sections:
wing_cross_section.wing_unit_chordwise_vector = self.unit_chordwise_vector

Expand All @@ -353,19 +368,19 @@ def __init__(

@property
def unit_up_vector(self):
"""This method sets a property for the wing's up orientation
vector, which is defined as the cross product of its unit chordwise and unit
normal vectors.
"""This method sets a property for the wing's up orientation vector in the
body frame, which is defined as the cross product of its unit chordwise and
unit normal vectors.
:return: (3,) array of floats
This is the wing's unit up vector. The units are meters.
This is the wing's unit up vector in the body frame. The units are meters.
"""
return np.cross(self.unit_chordwise_vector, self.unit_normal_vector)

@property
def projected_area(self):
"""This method defines a property for the area of the wing projected onto the
plane defined by the projected unit normal vector.
plane defined by its unit up vector.
If the wing is symmetric, the area of the mirrored half is included.
Expand Down Expand Up @@ -504,6 +519,7 @@ def mean_aerodynamic_chord(self):
return integral / self.projected_area


# ToDo: Modify this object to make its parameters in the wing object's frame.
class WingCrossSection:
"""This class is used to contain the cross sections of a Wing object.
Expand Down
8 changes: 8 additions & 0 deletions pterasoftware/meshing.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
from . import panel


# ToDo: Make sure the panel locations are calculated correctly now that the wing
# cross section objects are defined in their parent wing frame.
def mesh_wing(wing):
"""This function takes in an object of the Wing class and creates a quadrilateral
mesh of its geometry, and then populates the object's panels with the mesh data.
Expand Down Expand Up @@ -287,6 +289,8 @@ def mesh_wing(wing):
wing.panels = wing_panels


# ToDo: Make sure the panel locations are calculated correctly now that the wing
# cross section objects are defined in their parent wing frame.
def get_wing_section_panel_vertices(
wing_leading_edge,
inner_wing_cross_section,
Expand Down Expand Up @@ -401,6 +405,8 @@ def get_wing_section_panel_vertices(
]


# ToDo: Make sure the panel locations are calculated correctly now that the wing
# cross section objects are defined in their parent wing frame.
def get_transpose_mcl_vectors(inner_airfoil, outer_airfoil, chordwise_coordinates):
"""This function takes in the inner and outer airfoils of a wing cross section
and its chordwise coordinates. It returns a list of four column vectors. They
Expand Down Expand Up @@ -450,6 +456,8 @@ def get_transpose_mcl_vectors(inner_airfoil, outer_airfoil, chordwise_coordinate
]


# ToDo: Make sure the panel locations are calculated correctly now that the wing
# cross section objects are defined in their parent wing frame.
def get_wing_section_panels(
front_left_vertices,
front_right_vertices,
Expand Down

0 comments on commit 2f71842

Please sign in to comment.