Airfoil Module
This module contains a number of tools to help analyze airfoil geometries in 2D.
AfGage
An enumeration class used to specify a method for locating a gage points on an airfoil cross-section.
OnCamber
A gaging method that measures a distance along the mean camber line. A positive distance will be from the leading edge towards the trailing edge, and a negative distance will be from the trailing edge towards the leading edge.
__init__(d)
Create a specification for a gage point that is a distance d
along the mean camber line. A positive
distance will be from the leading edge towards the trailing edge, and a negative distance will be from the
trailing edge towards the leading edge.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
d
|
float
|
the distance along the mean camber line to find the position |
required |
Radius
A gaging method that measures by intersection with a circle of a given radius centered on either the leading or trailing edge point. A positive radius indicates that the circle is located on the leading edge while a negative radius indicates that the circle is located on the trailing edge.
__init__(r)
Create a specification for a gage point that is located at the intersection of a circle of radius r
with
the airfoil cross-section. A positive radius indicates that the circle is located on the leading edge while
a negative radius indicates that the circle is located on the trailing edge.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
r
|
float
|
the radius of the circle to find the position |
required |
AirfoilGeometry
This class produces and contains the result of the geometric analysis of an airfoil cross-section. It contains:
-
The mean camber line
-
The segregated geometry of the upper (suction, convex) and lower (pressure, concave) faces
-
The detected position and geometry of the leading and trailing edges
-
The array of inscribed circles identified during the analysis
From this information, thicknesses and other measurements can be made on the airfoil.
See the from_analyze
method for how to perform the analysis creating an instance of this class.
camber
property
Gets the mean camber line of the airfoil cross-section. The curve will be oriented so that the first point is at the leading edge of the airfoil and the last point is at the trailing edge.
Returns:
Type | Description |
---|---|
Curve2
|
The mean camber line of the airfoil cross-section as a |
circle_array
property
Returns the list of inscribed circles as a numpy array of shape (N, 3) where N is the number of inscribed circles. The first two columns are the x and y coordinates of the circle center, and the third column is the radius of the circle.
Returns:
Type | Description |
---|---|
NDArray[float]
|
A numpy array of shape (N, 3) containing the inscribed circles |
leading
property
Gets the result of the leading edge detection algorithm.
lower
property
The curve representing the lower (pressure, concave) side of the airfoil cross-section. The curve will be oriented in the same winding direction as the original section, so the first point may be at either the leading or trailing edge based on the airfoil geometry and the coordinate system.
Returns:
Type | Description |
---|---|
Curve2 | None
|
A |
trailing
property
Gets the result of the trailing edge detection algorithm.
upper
property
The curve representing the upper (suction, convex) side of the airfoil cross-section. The curve will be oriented in the same winding direction as the original section, so the first point may be at either the leading or trailing edge based on the airfoil geometry and the coordinate system.
Returns:
Type | Description |
---|---|
Curve2 | None
|
A |
from_analyze(section, refine_tol, camber_orient, leading, trailing, face_orient)
staticmethod
This method attempts to extract the airfoil geometry from the given airfoil cross-section using only the geometric information embedded in the section. It is suitable for airfoil cross-sections with clean, low-noise or noise-free data, such as those which come from nominal CAD data or from very clean scans/samples of airfoils with smooth, continuous surfaces with little to no defects.
The cross-section data must also be only the outer surface of the airfoil, with no internal features or points. The vertices should be ordered in a counter-clockwise direction, but the section may be open on one side and no particular orientation or position in the XY plane is required.
Internally, this operation will attempt to:
-
Extract the unambiguous inscribed circles from the cross-section using an iterative stepping/refinement method (see
compute_inscribed_circles
for more detail). -
Orient the mean camber line (determine which side is the leading edge and which side is the trailing edge) based on the method specified in
camber_orient
. -
Extract the exact position (and optionally, the geometry) of the leading and trailing edges based on the methods specified in
leading
andtrailing
, respectively. -
Identify and extract the upper (suction, convex) and lower (pressure, concave) faces of the airfoil based on the method specified in
face_orient
.
If successful in all of these steps, the method will return an instance of AirfoilGeometry
containing the
results of the analysis. If any of the steps fail, the method will raise an error.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
section
|
Curve2
|
The curve representing the airfoil cross-section |
required |
refine_tol
|
float
|
A general tolerance used in the analysis, typically used to refine results until the error or difference between two values is less than this value. It is also used in certain methods as a common reference tolerance, where the method will use a fraction of this value as a threshold for convergence or error. |
required |
camber_orient
|
MclOrientEnum
|
The method to use to orient the mean camber line of the airfoil. |
required |
leading
|
EdgeFindEnum
|
The method to use to detect the leading edge of the airfoil. |
required |
trailing
|
EdgeFindEnum
|
The method to use to detect the trailing edge of the airfoil. |
required |
face_orient
|
FaceOrientEnum
|
The method to identify the upper and lower faces of the airfoil. |
required |
Returns:
Type | Description |
---|---|
AirfoilGeometry
|
An instance of |
get_thickness(gage)
Get the thickness dimension of the airfoil cross-section. The 'a' point of the distance will be on the lower surface of the airfoil, and the 'b' point will be on the upper surface.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
gage
|
AfGageEnum
|
the gaging method to use |
required |
Returns:
Type | Description |
---|---|
Distance2
|
a |
get_tmax()
Get the maximum thickness dimension of the airfoil cross-section. The 'a' point of the distance will be on the lower surface of the airfoil, and the 'b' point will be on the upper surface.
Returns:
Type | Description |
---|---|
Distance2
|
a |
get_tmax_circle()
Get the circle representing the maximum thickness dimension of the airfoil cross-section.
Returns:
Type | Description |
---|---|
Circle2
|
a |
EdgeFind
An enumeration of the possible techniques to find the leading and/or trailing edge geometry of an airfoil.
Intersect
This algorithm will simply intersect the end of the inscribed circles camber curve with the airfoil cross-section. This is the fastest method with the least amount of assumptions, and makes sense for airfoil edges where you know the mean camber line has very low curvature in the vicinity of the edge.
Do not use this method if you know that the airfoil cross-section is open/incomplete on this side, as it will throw an error if the MCL does not intersect the cross-section.
__init__()
Create a specification which will attempt to find the edge geometry by intersecting the end of the inscribed circles camber curve with the airfoil cross-section. Use on known closed airfoil cross-sections with low curvature near the edge.
Open
This algorithm will not attempt to find edge geometry, and will simply leave the inscribed circles for the side as they are. Use this if you know that the airfoil cross-section is open/incomplete on this side, and you don't care to extend the MCL any further.
__init__()
Create a specification which assumes that the airfoil cross-section is open/incomplete on this side, and makes no attempt to find the edge geometry beyond the unambiguous inscribed circles.
OpenIntersect
This algorithm is also for an open edge, but unlike Open
it will attempt to refine the end of the MCL and
extend it to intersect the line segment which spans the open gap where the edge should be. This is useful on
partial cross-sections where you would still like to extend the MCL as much as possible.
It works by intersecting the end of the inscribed circles camber curve with the open gap in the airfoil cross-section, filling and refining more inscribed circles between the last circle and the intersection point, and repeating until the location of the end converges to within 1/100th of the general refinement tolerance.
__init__(max_iter)
This algorithm will attempt to find the edge geometry by intersecting the end of the inscribed circles camber curve with the open gap in the airfoil cross-section, then refining the end of the MCL with more inscribed circles until the location of the end converges to within 1/100th of the general refinement tolerance.
If the maximum number of iterations is reached before convergence, the method will throw an error instead.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
max_iter
|
int
|
the maximum number of iterations to attempt to find the edge geometry |
required |
RansacRadius
This technique uses RANSAC (Random Sample Consensus) to find a constant radius leading/trailing edge circle
that fits the greatest number of points leftover at the edge within the tolerance in_tol
.
The method will try n
different combinations of three points picked at random from the remaining points
at the edge, construct a circle, and then count the number of points within in_tol
distance of the circle
perimeter. The circle with the most points within tolerance will be considered the last inscribed circle.
The MCL will be extended to this final circle, and then intersected with the airfoil cross-section to find the final edge point.
__init__(in_tol, n=500)
Create a specification which will attempt to find the edge geometry by Random Sample Consensus of a constant radius at the edge of the airfoil cross-section. This is useful for airfoils known to have a constant radius edge and on section data which is relatively clean and has low noise.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
in_tol
|
float
|
the max distance from the circle perimeter for a point to be considered a RANSAC inlier |
required |
n
|
int
|
The number of RANSAC iterations to perform |
500
|
EdgeResult
Represents the results of an airfoil edge detection operation, containing both a point on the airfoil cross-section that was detected as the edge, and optional geometric information about the edge depending on the method used.
geometry
property
Gets the geometric information about the edge that was detected.
-
This will be an instance of
EdgeType
if the algorithm could not provide more detailed geometric information about the edge beyond open/closed. -
This will be an instance of
Arc2
in the case of constant radius edge detection.
Returns:
Type | Description |
---|---|
EdgeType | Arc2
|
The geometric information about the edge that was detected |
point
property
Gets the point on the airfoil cross-section that was detected as the edge.
Returns:
Type | Description |
---|---|
Point2
|
The point on the airfoil cross-section that was detected as the edge |
EdgeType
Bases: Enum
An enumeration of the possible non-geometric types of edges that can be detected on an airfoil cross-section as the result of an edge finding operation. When one of these types is returned, it means that the edge finding algorithm could not provide more detailed geometric information about the edge.
Closed = 1
class-attribute
instance-attribute
Represents an edge that is closed, where the airfoil cross-section has contiguous vertices through the edge.
Open = 0
class-attribute
instance-attribute
Represents an open edge, where the airfoil cross-section is incomplete and/or not closed.
FaceOrient
An enumeration of the possible ways to orient the upper/lower (suction/pressure, convex/concave) faces of an airfoil cross-section.
Detect
In an airfoil with an MCL that exhibits curvature, this will attempt to detect which direction the camber line curves and thus identify convex/concave. This will fail if the MCL is straight.
__init__()
Create a new face orientation parameter that will attempt to detect the orientation of the faces based on the curvature of the mean camber line.
UpperDir
This method will orient the faces based on a vector direction provided by the user.
__init__(x, y)
Create a new upper direction parameter. The x and y arguments are components of a direction vector which should distinguish the upper (pressure side, convex) face of the airfoil. At the center of the mean camber line, an intersection in this direction will be taken with each of the two faces. The intersection that is further in the direction of this vector will be considered the upper face of the airfoil, and the other will be considered the lower face.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
x
|
float
|
the x component of the upper direction vector |
required |
y
|
float
|
the y component of the upper direction vector |
required |
InscribedCircle
Represents an inscribed circle in an airfoil cross-section. The circle is contained within the airfoil cross-section and is tangent to the airfoil section at two points.
circle
property
Gets the circle object associated with this inscribed circle.
Returns:
Type | Description |
---|---|
Circle2
|
The circle entity for the inscribed circle |
contact_a
property
Get a contact point of the inscribed circle with one side of the airfoil cross-section. Inscribed circles
computed together will have a consistent meaning of a
and b
sides, but which is the upper or lower surface
will depend on the ordering of the circles and the coordinate system of the airfoil.
Returns:
Type | Description |
---|---|
Point2
|
The first contact point of the inscribed circle with the airfoil cross-section |
contact_b
property
Get the other contact point of the inscribed circle with the airfoil cross-section. Inscribed circles computed
together will have a consistent meaning of a
and b
sides, but which is the upper or lower surface will
depend on the ordering of the circles and the coordinate system of the airfoil.
Returns:
Type | Description |
---|---|
Point2
|
The second contact point of the inscribed circle with the airfoil cross-section |
MclOrient
An enumeration of the possible ways to orient (to identify which side is the leading edge and which side is the trailing edge) the mean camber line of an airfoil.
DirFwd
This method will orient the airfoil based on a vector direction provided by the user.
__init__(x, y)
Create a new forward direction parameter. The x and y arguments are components of a direction vector which should distinguish the forward (leading edge) direction of the airfoil. The position of the first and last inscribed circle will be projected onto this vector, and the larger result (the one that is more in the direction of this vector) will be considered the leading edge of the airfoil.
For instance, if you know that the airfoil is oriented so that the leading edge will have a smaller x value
than the trailing edge, DirFwd(-1, 0)
will correctly orient the airfoil.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
x
|
float
|
the x component of the forward direction vector |
required |
y
|
float
|
the y component of the forward direction vector |
required |
TmaxFwd
This method will take advantage of the fact that for most typical subsonic airfoils the maximum thickness point is closer to the leading edge than the trailing edge.
__init__()
Create a specification for orienting the mean camber line based on which side the maximum thickness point is closer to. This method will assume that the maximum thickness point is closer to the leading edge than the trailing edge.
compute_inscribed_circles(section, refine_tol)
Compute the unambiguous inscribed circles of an airfoil cross-section.
The cross-section is represented by a curve in the x-y plane. The curve does not need to be closed, but the points should be oriented in a counter-clockwise direction and should only contain data from the outer surface of the airfoil (internal features/points should not be part of the data).
The method used to compute these circles is:
- We calculate the convex hull of the points in the section and find the longest distance between any two points.
- At the center of the longest distance line, we draw a perpendicular line and look for exactly two intersections with the section. We assume that one of these is on the upper surface of the airfoil and the other is on the lower, though it does not matter which is which.
- We fit the maximum inscribed circle whose center is constrained to the line between these two points. The
location and radius of this circle is refined until it converges to within 1/100th of
refine_tol
. - The inscribed circle has two contact points with the section. The line between these contact points is a good approximation of the direction orthogonal to the mean camber line near the circle. We create a parallel line to this one, advancing from the circle center by 1/4 of the circle radius, and looking for exactly two intersections with the section. If we fail, we try again with a slightly less aggressive advancement until we either succeed or give up.
- We fit the maximum inscribed circle whose center is constrained to the new line, and refine it as in step 3.
- We recursively fit inscribed circles between this new circle and the previous one until the error between the
position and radius of any circle is less than
refine_tol
from the linear interpolation between its next and previous neighbors. - We repeat the process from step 4 until the distance between the center of the most recent circle and the farthest point in the direction of the next advancement is less than 1/4 of the radius of the most recent circle. This terminates the process before we get too close to the leading or trailing edge of the airfoil.
- We repeat the process from step 3, but this time in the opposite direction from the first circle. This will give us the inscribed circles on the other side of the airfoil.
When finished, we have a list of inscribed circles from the unambiguous regions (not too close to the leading or trailing edges) of the airfoil cross-section. The circles are ordered from one side of the airfoil to the other, but the order may be either from the leading to the trailing edge or vice versa.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
section
|
Curve2
|
the curve representing the airfoil cross-section. |
required |
refine_tol
|
float
|
a tolerance used when refining the inscribed circles, see description for details. |
required |
Returns:
Type | Description |
---|---|
List[InscribedCircle]
|
a list of inscribed circle objects whose order is contiguous but may be in either direction |