Skip to content

Commit 7fecfd0

Browse files
authored
Add airfoil transonic dataset (#46)
1 parent 7199dbd commit 7fecfd0

File tree

9 files changed

+204
-0
lines changed

9 files changed

+204
-0
lines changed

smithers/dataset/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
from .datasets.graetz import GraetzDataset
66
from .datasets.unsteady_heat import UnsteadyHeatDataset
77
from .datasets.lid_cavity import LidCavity
8+
from .datasets.airfoil_transonic import AirfoilTransonicDataset
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
from ..abstract_dataset import AbstractDataset
2+
import os
3+
import numpy as np
4+
import matplotlib
5+
import matplotlib.pyplot as plt
6+
import matplotlib.tri as tri
7+
from mpl_toolkits.axes_grid1 import make_axes_locatable
8+
from scipy.interpolate import CubicSpline
9+
10+
11+
class AirfoilTransonicDataset(AbstractDataset):
12+
13+
parametric = True
14+
time_dependent = False
15+
description = "Transonic flow past a NACA 0012 airfoil"
16+
data_directory = os.path.join(os.path.dirname(__file__),
17+
'airfoil_transonic')
18+
19+
def __init__(self):
20+
'''
21+
Initialize the dataset and structure it in dictionaries.
22+
'''
23+
self.params = np.load(os.path.join(self.data_directory, 'params.npy'))
24+
v_internal = np.load(os.path.join(self.data_directory,
25+
'snapshots_v_internal.npy'))
26+
p_internal = np.load(os.path.join(self.data_directory,
27+
'snapshots_p_internal.npy'))
28+
p_airfoil = np.load(os.path.join(self.data_directory,
29+
'snapshots_p_airfoil.npy'))
30+
wn_airfoil = np.load(os.path.join(self.data_directory,
31+
'snapshots_wn_airfoil.npy'))
32+
33+
self.snapshots = {
34+
'internal': {'mag(v)': v_internal, 'p': p_internal},
35+
'airfoil': {'p': p_airfoil, 'wallshear_normal': wn_airfoil}
36+
}
37+
coords_internal = np.load(os.path.join(self.data_directory,
38+
'coords_internal.npy'))
39+
coords_airfoil = np.load(os.path.join(self.data_directory,
40+
'coords_airfoil.npy'))
41+
self.pts_coordinates = {
42+
'internal': coords_internal, 'airfoil': coords_airfoil
43+
}
44+
self.auxiliary_triang = tri.Triangulation(coords_internal[0, :],
45+
coords_internal[1, :])
46+
self.auxiliary_triang.set_mask(self._mask_airfoil())
47+
48+
def _coords_airfoil(self, which='pos'):
49+
'''
50+
Get the positive (if which='pos') or negative (if which='neg')
51+
coordinates of the airfoil.
52+
'''
53+
x_airfoil = self.pts_coordinates['airfoil'][0, :]
54+
y_airfoil = self.pts_coordinates['airfoil'][1, :]
55+
if which=='pos':
56+
indices = y_airfoil >= 0
57+
elif which=='neg':
58+
indices = y_airfoil <= 0
59+
60+
x_airfoil_which = sorted(x_airfoil[indices])
61+
y_airfoil_which = y_airfoil[indices][
62+
np.argsort(x_airfoil[indices])]
63+
return x_airfoil_which, y_airfoil_which
64+
65+
def _f_airfoil_neg(self, tol=1e-4):
66+
'''
67+
Return a function that represents the negative part of the airfoil.
68+
'''
69+
x_airfoil_neg, y_airfoil_neg = self._coords_airfoil(which='neg')
70+
f_neg = CubicSpline(x_airfoil_neg, y_airfoil_neg)
71+
array = []
72+
for x in self.pts_coordinates['internal'][0, :]:
73+
if x >= 0 and x <= 1:
74+
array.append(f_neg(x) - tol)
75+
else:
76+
array.append(np.nan)
77+
return np.array(array)
78+
79+
def _f_airfoil_pos(self, tol=1e-4):
80+
'''
81+
Return a function that represents the positive part of the airfoil.
82+
'''
83+
x_airfoil_pos, y_airfoil_pos = self._coords_airfoil(which='pos')
84+
f_pos = CubicSpline(x_airfoil_pos, y_airfoil_pos)
85+
array = []
86+
for x in self.pts_coordinates['internal'][0, :]:
87+
if x >= 0 and x <= 1:
88+
array.append(f_pos(x) + tol)
89+
else:
90+
array.append(np.nan)
91+
return np.array(array)
92+
93+
def _mask_airfoil(self):
94+
'''
95+
Mask the triangles that are inside the airfoil (useful for plots).
96+
'''
97+
coords = self.pts_coordinates['internal']
98+
x_airfoil = self.pts_coordinates['airfoil'][0, :]
99+
y_airfoil = self.pts_coordinates['airfoil'][1, :]
100+
isbad = (np.greater(coords[0, :], x_airfoil.min()) &
101+
np.less(coords[0, :], x_airfoil.max()) &
102+
np.less(coords[1, :], self._f_airfoil_pos()) &
103+
np.greater(coords[1, :], self._f_airfoil_neg()))
104+
triangles = self.auxiliary_triang.triangles
105+
mask = np.all(np.where(isbad[triangles], True, False), axis=1)
106+
return mask
107+
108+
def plot_internal(self, snaps_array, idx=0, title='Snapshot', namefig=None,
109+
lim_x=(-0.5, 2), lim_y=(-0.5, 1), figsize=(8, 4), logscale=False):
110+
'''
111+
Plot a snapshot of the internal flow.
112+
113+
Parameters
114+
----------
115+
snaps_array : numpy.ndarray
116+
Snapshots of the internal flow (also external, not only
117+
self.snapshots['internal']).
118+
The shape should be (nparams, npoints).
119+
idx : int, optional
120+
Index of the snapshot to plot. The default is 0.
121+
title : str, optional
122+
Title of the plot. The default is 'Snapshot'.
123+
namefig : str, optional
124+
Name of the file where the plot is saved. The default is None.
125+
lim_x : tuple, optional
126+
Limits of the x-axis. The default is (-0.5, 2).
127+
lim_y : tuple, optional
128+
Limits of the y-axis. The default is (-0.5, 1).
129+
figsize: tuple, optional
130+
Size of the output figure. The default is (8, 4).
131+
'''
132+
fig, ax = plt.subplots(1, 1, figsize=figsize)
133+
snapshot = snaps_array[idx, :]
134+
if logscale:
135+
lognorm = matplotlib.colors.LogNorm(vmin=snapshot.min()+1e-12,
136+
vmax=snapshot.max())
137+
c = ax.tripcolor(self.auxiliary_triang, snapshot, cmap='rainbow',
138+
shading='gouraud', norm=lognorm)
139+
else:
140+
c = ax.tripcolor(self.auxiliary_triang, snapshot, cmap='rainbow',
141+
shading='gouraud')
142+
ax.plot(self._coords_airfoil()[0], self._coords_airfoil()[1],
143+
color='black', lw=0.5)
144+
ax.plot(self._coords_airfoil(which='neg')[0],
145+
self._coords_airfoil(which='neg')[1],
146+
color='black', lw=0.5)
147+
ax.set_aspect('equal')
148+
if lim_x is not None:
149+
ax.set_xlim(lim_x)
150+
if lim_y is not None:
151+
ax.set_ylim(lim_y)
152+
if title is not None:
153+
ax.set_title(title)
154+
divider = make_axes_locatable(ax)
155+
cax = divider.append_axes("right", size= "5%", pad=0.1)
156+
plt.colorbar(c, cax=cax)
157+
if namefig is not None:
158+
fig.savefig(namefig, dpi=300)
159+
plt.show()
160+
161+
def plot_airfoil(self, snaps_array, idx=0, title='Snapshot', namefig=None,
162+
lim_x=(-0.1, 1.1), lim_y=(-0.2, 0.2), figsize=(8, 4)):
163+
'''
164+
Plot a snapshot on the airfoil.
165+
166+
Parameters
167+
----------
168+
snaps_array : numpy.ndarray
169+
Snapshot on the airfoil (also external, not only
170+
self.snapshots['airfoil']).
171+
The shape should be (nparams, npoints).
172+
idx : int, optional
173+
Index of the snapshot to plot. The default is 0.
174+
title : str, optional
175+
Title of the plot. The default is 'Snapshot'.
176+
namefig : str, optional
177+
Name of the file where the plot is saved. The default is None.
178+
lim_x : tuple, optional
179+
Limits of the x-axis. The default is (-0.1, 1.1).
180+
lim_y : tuple, optional
181+
Limits of the y-axis. The default is (-0.2, 0.2).
182+
figsize: tuple, optional
183+
Size of the output figure. The default is (8, 4).
184+
'''
185+
fig, ax = plt.subplots(1, 1, figsize=figsize)
186+
snapshot = snaps_array[idx, :]
187+
coords = self.pts_coordinates['airfoil']
188+
ax.grid()
189+
c = ax.scatter(coords[0, :], coords[1, :], c=snapshot, s=10)
190+
ax.set_aspect('equal')
191+
if lim_x is not None:
192+
ax.set_xlim(lim_x)
193+
if lim_y is not None:
194+
ax.set_ylim(lim_y)
195+
if title is not None:
196+
ax.set_title(title)
197+
divider = make_axes_locatable(ax)
198+
cax = divider.append_axes("right", size= "5%", pad=0.1)
199+
plt.colorbar(c, cax=cax)
200+
if namefig is not None:
201+
fig.savefig(namefig, dpi=300)
202+
plt.show()
203+
7.13 KB
Binary file not shown.
355 KB
Binary file not shown.
928 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)