Skip to content

Commit ef147fe

Browse files
RobPasMuepyansys-ci-botpre-commit-ci[bot]PipKat
authored
docs: creating a NACA airfoil example (#1167)
Co-authored-by: pyansys-ci-bot <pyansys.github.bot@ansys.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com>
1 parent a9d4779 commit ef147fe

File tree

7 files changed

+266
-0
lines changed

7 files changed

+266
-0
lines changed

doc/changelog.d/1167.miscellaneous.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
docs: creating a NACA airfoil example
Loading

doc/source/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ def intersphinx_pyansys_geometry(switcher_version: str):
276276
"examples/03_modeling/scale_map_mirror_bodies": "_static/thumbnails/scale_map_mirror_bodies.png", # noqa: E501
277277
"examples/03_modeling/sweep_chain_profile": "_static/thumbnails/sweep_chain_profile.png",
278278
"examples/03_modeling/export_design": "_static/thumbnails/export_design.png",
279+
"examples/04_applied/01_naca_airfoils": "_static/thumbnails/naca_airfoils.png",
279280
}
280281
nbsphinx_epilog = """
281282
----

doc/source/examples.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,13 @@ These examples demonstrate service-based modeling operations.
4141
examples/03_modeling/scale_map_mirror_bodies.mystnb
4242
examples/03_modeling/sweep_chain_profile.mystnb
4343
examples/03_modeling/export_design.mystnb
44+
45+
Applied examples
46+
----------------
47+
48+
These examples demonstrate the usage of PyAnsys Geometry for real-world
49+
applications.
50+
51+
.. nbgallery::
52+
53+
examples/04_applied/01_naca_airfoils.mystnb

doc/source/examples/03_modeling/add_design_material.mystnb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ material = Material(
7474
material.add_property(MaterialPropertyType.TENSILE_STRENGTH, "TensileProp", Quantity(45))
7575
design.add_material(material)
7676
```
77+
7778
## Extrude sketch to create body
7879

7980
Extrude the sketch to create the body and then assign a material to it.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.fmd
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
---
2+
jupytext:
3+
text_representation:
4+
extension: .mystnb
5+
format_name: myst
6+
format_version: 0.13
7+
jupytext_version: 1.14.1
8+
kernelspec:
9+
display_name: Python 3 (ipykernel)
10+
language: python
11+
name: python3
12+
---
13+
# Applied: Create a NACA 4-digit airfoil
14+
15+
NACA airfoils are a series of airfoil shapes for aircraft wings developed by
16+
the National Advisory Committee for Aeronautics (NACA). They are a standardized
17+
system of airfoil shapes that are defined by a series of digits. The digits,
18+
which indicate the shape of the airfoil, are used to create the airfoil shape.
19+
20+
Each digit in the NACA airfoil number has a specific meaning:
21+
22+
- The first digit defines the maximum camber as a percentage of the chord length.
23+
- The second digit defines the position of the maximum camber as a percentage of the chord length.
24+
- The last two digits define the maximum thickness of the airfoil as a percentage of the chord length.
25+
26+
To fully understand the previous definitions, it is important to know that the chord length
27+
is the length of the airfoil from the leading edge to the trailing edge. The camber is the
28+
curvature of the airfoil, and the thickness is the distance between the upper and lower surfaces.
29+
30+
Symmetric airfoils have a camber of 0% and consequently, the first two digits of the NACA number
31+
are 0. For example, the NACA 0012 airfoil is a symmetric airfoil with a maximum thickness of 12%.
32+
33+
## Define the NACA 4-digit airfoil equation
34+
35+
The following code uses the equation for a NACA 4-digit airfoil to create
36+
a set of points that define the airfoil shape. These points are ``Point2D`` objects
37+
in PyAnsys Geometry.
38+
39+
```{code-cell} ipython3
40+
from typing import List, Union
41+
42+
import numpy as np
43+
44+
from ansys.geometry.core.math import Point2D
45+
46+
def naca_airfoil_4digits(number: Union[int, str], n_points: int = 200) -> List[Point2D]:
47+
"""
48+
Generate a NACA 4-digits airfoil.
49+
50+
Parameters
51+
----------
52+
number : int or str
53+
NACA 4-digit number.
54+
n_points : int
55+
Number of points to generate the airfoil. The default is ``200``.
56+
Number of points in the upper side of the airfoil.
57+
The total number of points is ``2 * n_points - 1``.
58+
59+
Returns
60+
-------
61+
List[Point2D]
62+
List of points that define the airfoil.
63+
"""
64+
# Check if the number is a string
65+
if isinstance(number, str):
66+
number = int(number)
67+
68+
# Calculate the NACA parameters
69+
m = number // 1000 * 0.01
70+
p = number // 100 % 10 * 0.1
71+
t = number % 100 * 0.01
72+
73+
# Generate the airfoil
74+
points = []
75+
for i in range(n_points):
76+
77+
# Make it a exponential distribution so the points are more concentrated
78+
# near the leading edge
79+
x = (1 - np.cos(i / (n_points - 1) * np.pi)) / 2
80+
81+
# Check if it is a symmetric airfoil or not
82+
if p == 0 and m == 0:
83+
# Camber line is zero in this case
84+
yc = 0
85+
dyc_dx = 0
86+
else:
87+
# Compute the camber line
88+
if x < p:
89+
yc = m / p**2 * (2 * p * x - x**2)
90+
dyc_dx = 2 * m / p**2 * (p - x)
91+
else:
92+
yc = m / (1 - p) ** 2 * ((1 - 2 * p) + 2 * p * x - x**2)
93+
dyc_dx = 2 * m / (1 - p) ** 2 * (p - x)
94+
95+
# Compute the thickness
96+
yt = 5 * t * (0.2969 * x**0.5
97+
- 0.1260 * x
98+
- 0.3516 * x**2
99+
+ 0.2843 * x**3
100+
- 0.1015 * x**4)
101+
102+
# Compute the angle
103+
theta = np.arctan(dyc_dx)
104+
105+
# Compute the points (upper and lower side of the airfoil)
106+
xu = x - yt * np.sin(theta)
107+
yu = yc + yt * np.cos(theta)
108+
xl = x + yt * np.sin(theta)
109+
yl = yc - yt * np.cos(theta)
110+
111+
# Append the points
112+
points.append(Point2D([xu, yu]))
113+
points.insert(0, Point2D([xl, yl]))
114+
115+
# Remove the first point since it is repeated
116+
if i == 0:
117+
points.pop(0)
118+
119+
return points
120+
121+
```
122+
123+
## Example of a symmetric airfoil: NACA 0012
124+
125+
Now that the function for generating a NACA 4-digit airfoil is generated, this code creates a NACA 0012
126+
airfoil, which is symmetric. This airfoil has a maximum thickness of 12%. The NACA number is a constant.
127+
128+
```{code-cell} ipython3
129+
NACA_AIRFOIL = "0012"
130+
```
131+
132+
### Required imports
133+
134+
Before you start creating the airfoil points, you must import the necessary modules to create the
135+
airfoil using PyAnsys Geometry.
136+
137+
```{code-cell} ipython3
138+
from ansys.geometry.core import launch_modeler
139+
from ansys.geometry.core.sketch import Sketch
140+
```
141+
142+
### Generate the airfoil points
143+
144+
Using the function defined previously, you generate the points that define the NACA 0012 airfoil.
145+
Create a ``Sketch`` object and add the points to it. Then, approximate the airfoil using
146+
straight lines between the points.
147+
148+
```{code-cell} ipython3
149+
# Create a sketch
150+
sketch = Sketch()
151+
152+
# Generate the points of the airfoil
153+
points = naca_airfoil_4digits(NACA_AIRFOIL)
154+
155+
# Create the segments of the airfoil
156+
for i in range(len(points) - 1):
157+
sketch.segment(points[i], points[i + 1])
158+
159+
# Close the airfoil
160+
sketch.segment(points[-1], points[0])
161+
162+
# Plot the airfoil
163+
sketch.plot()
164+
```
165+
166+
### Create the 3D airfoil
167+
168+
Once the ``Sketch`` object is created, you create a 3D airfoil. For this operation, you must create
169+
a modeler object, create a design object, and extrude the sketch.
170+
171+
```{code-cell} ipython3
172+
# Launch the modeler
173+
modeler = launch_modeler()
174+
175+
# Create the design
176+
design = modeler.create_design(f"NACA_Airfoil_{NACA_AIRFOIL}")
177+
178+
# Extrude the airfoil
179+
design.extrude_sketch("Airfoil", sketch, 1)
180+
181+
# Plot the design
182+
design.plot()
183+
```
184+
185+
### Save the design
186+
187+
Finally, save the design to a file. This file can be used in other applications or imported
188+
into a simulation software. This code saves the design as an FMD file, which can then be imported
189+
into Ansys Fluent.
190+
191+
```{code-cell} ipython3
192+
# Save the design
193+
file = design.export_to_fmd()
194+
print(f"Design saved to {file}")
195+
```
196+
197+
## Example of a cambered airfoil: NACA 6412
198+
199+
This code creates a NACA 6412 airfoil, which is cambered. This airfoil has a maximum
200+
camber of 6% and a maximum thickness of 12%. After overriding the NACA number, the code generates the
201+
airfoil points.
202+
203+
```{code-cell} ipython3
204+
NACA_AIRFOIL = "6412"
205+
```
206+
207+
### Generate the airfoil points
208+
209+
As before, you generate the points that define the NACA 6412 airfoil. Create a
210+
``Sketch`` object and add the points to it. Then, approximate the airfoil using straight lines.
211+
212+
```{code-cell} ipython3
213+
# Create a sketch
214+
sketch = Sketch()
215+
216+
# Generate the points of the airfoil
217+
points = naca_airfoil_4digits(NACA_AIRFOIL)
218+
219+
# Create the segments of the airfoil
220+
for i in range(len(points) - 1):
221+
sketch.segment(points[i], points[i + 1])
222+
223+
# Close the airfoil
224+
sketch.segment(points[-1], points[0])
225+
226+
# Plot the airfoil
227+
sketch.plot()
228+
```
229+
230+
### Create the 3D airfoil
231+
232+
```{code-cell} ipython3
233+
# Launch the modeler
234+
modeler = launch_modeler()
235+
236+
# Create the design
237+
design = modeler.create_design(f"NACA_Airfoil_{NACA_AIRFOIL}")
238+
239+
# Extrude the airfoil
240+
design.extrude_sketch("Airfoil", sketch, 1)
241+
242+
# Plot the design
243+
design.plot()
244+
```
245+
246+
### Save the design
247+
248+
```{code-cell} ipython3
249+
# Save the design
250+
file = design.export_to_fmd()
251+
print(f"Design saved to {file}")
252+
```

0 commit comments

Comments
 (0)