Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
pjuangph committed Mar 7, 2022
0 parents commit c88636a
Show file tree
Hide file tree
Showing 50 changed files with 6,259 additions and 0 deletions.
154 changes: 154 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so
uiuc*.csv

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
.vscode/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# Large files
test*.pt
train*.pt
*.off
*.tar.gz
*.DS_Store
*.npz
*.csv
*.pt.tar


.vscode/
*.gz
*.cp
*.tar
*.pth
*.h5
*.tmp
*$*
*.pickle
*.txt
*.pt
1 change: 1 addition & 0 deletions .gitignore_global
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.DS_Store
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Airfoil Learning
The goal of this repository is to outline a method of using graph neural networks and deep neural networks to predict the Lift and Drag of 2D Airfoils. Graph Neural Networks investigate the relationship between nodes through edges and edge attributes. Graph relationships are all around us, our social networks on Facebook, the products we purchase or are interested in on Amazon, molecular interactions. This project investigates using the connectivity of points that describe a 2D airfoil to predict performance.

## Data Structure

* (Feature) Vertices (x,y,z)
* (Feature) Edge_Connectivity (edge_index1,edge_index2)
* (Feature) Reynolds - flow velocity
* (Feature) Ncrit - turbulence parameter
* (Feature) Alpha - angle of attack
* (Label) Cl - Coefficient of Lift
* (Label) Cd - Coefficient of Drag
* (Label) Cm - Coefficient of Moment
* (Label) Cp - Pressure coefficient

Useful documentation on torch data object
* [Data Class](https://pytorch-geometric.readthedocs.io/en/latest/_modules/torch_geometric/data/data.html#Data)
* [In-Memory Datasets](https://pytorch-geometric.readthedocs.io/en/latest/notes/create_dataset.html#creating-in-memory-datasets)
* [Datasets](https://pytorch-geometric.readthedocs.io/en/latest/notes/create_dataset.html#creating-larger-datasets)


# Wiki links
[Getting Started with your Environment](https://gitlab.grc.nasa.gov/machine-learning/graph-networks/airfoil-learning/-/wikis/1.0-Getting-Started)

# Link to Dataset
Dataset can be found at https://nasa-public-data.s3.amazonaws.com/plot3d_utilities/airfoil-learning-dataset.zip

# Reporting Bugs
To report bugs, add a github issue. Instructions for adding github issues: https://www.youtube.com/watch?v=TKJ4RdhyB5Y

# License
[NASA Open Source Agreement](https://opensource.org/licenses/NASA-1.3)
1 change: 1 addition & 0 deletions generate_xfoil/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.json
73 changes: 73 additions & 0 deletions generate_xfoil/MakeFigures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import torch
import matplotlib.pyplot as plt
import glob
import os.path as osp
import numpy as np
import pandas as pd
from utils import csapi

# Folders
data = pd.read_pickle('scraped_airfoils_cp_clean.gz')
airfoil_names = data['name'].unique()
name = airfoil_names[np.random.randint(0,len(airfoil_names))]
print(name)

airfoil = data[data.name==name]
xss = np.array(airfoil['xss'])[0]; yss = np.array(airfoil['yss'])[0]; xps = np.array(airfoil['xps'])[0]; yps = np.array(airfoil['yps'])[0]

xv = np.linspace(0,1,20) # ! This fixes the number of points

yss_v = csapi(xss,yss,xv)
yps_v = csapi(xps,yps,xv)

x = np.concatenate( (xss, np.flip(xps[1:-1])) )
y = np.concatenate( (yss, np.flip(yps[1:-1])) )

polars = airfoil['polars'].iloc[0]
polars = polars[polars.Reynolds==100000]
polars = polars[polars.Ncrit==5]
alpha = polars.alpha
Cl = polars.Cl
Cp = np.concatenate(( polars.iloc[50].Cp_ss, np.flip( polars.iloc[50].Cp_ps[1:-1]) ))


# # Plot the Airfoil
# fig,ax = plt.subplots(1,1)
# x = np.concatenate((xss,np.flip(xps[1:-1])))
# y = np.concatenate((yss,np.flip(yps[1:-1])))

# x2 = np.concatenate((xv,np.flip(xv[1:-1])))
# y2 = np.concatenate((yss_v,np.flip(yps_v[1:-1])))
# # ax.plot(x,y, color='black', linestyle='solid', linewidth=2,marker='o', label='{0} points'.format(len(x)))
# ax.plot(x2,y2, color='red', linestyle='dashed', linewidth=4,marker='^', markersize=12,label='{0} points'.format(len(x2)))
# ax.set(xlim=(-0.05,1.05), ylim=(-0.15, 0.15))
# ax.legend(loc='lower right')
# ax.set_xlabel('x')
# ax.set_ylabel('y')
# ax.set_aspect('equal')
# fig.canvas.draw()
# fig.canvas.flush_events()
# plt.show()

# fig,ax = plt.subplots(1,1)
# # Plot Cl vs Alpha for a given Reynolds, Ncrit
# ax.plot(alpha,Cl, color='black', linestyle='solid', linewidth=2, label=name)
# ax.legend(loc='lower right')
# ax.set_xlabel('alpha [deg]')
# ax.set_ylabel('Cl')

# fig.canvas.draw()
# fig.canvas.flush_events()
# plt.show()

fig,ax = plt.subplots(1,1)
# Plot Cl vs Alpha for a given Reynolds, Ncrit
ax.plot(x,Cp, color='blue', linestyle='None', linewidth=2,marker='^', markersize=5, label=name)
ax.invert_yaxis()
ax.legend(loc='lower right')
ax.set_xlabel('x/c')
ax.set_ylabel('Cp')

fig.canvas.draw()
fig.canvas.flush_events()
plt.show()
60 changes: 60 additions & 0 deletions generate_xfoil/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Generate XFOIL
This folder has files needed to mine the airfoils and data from airfoil-tools.com.

# Installation
pip install -r requirements.txt

## Pytorch and Pytorch Geometric
These are the versions used at the time of testing. It may work with newer versions, if not please fix and submit a pull request or file a github issue.

- **CPU**: pip3 install torch==1.10.1+cu113 torchvision==0.11.2+cu113 torchaudio===0.10.1+cu113 -f https://download.pytorch.org/whl/cu113/torch_stable.html
- **GPU**: pip3 install torch torchvision torchaudio
- **Cpu version of PyTorch Geometric**: `pip install torch-scatter torch-sparse torch-cluster torch-spline-conv torch-geometric -f https://data.pyg.org/whl/torch-1.10.0+cpu.html`
- **GPU version of PyTorch Geometric**: `pip install torch-scatter torch-sparse torch-cluster torch-spline-conv torch-geometric -f https://data.pyg.org/whl/torch-1.10.0+cu113.html`

# Summary of the files and what they do
## Step1_GatherData.py
This file mines the website airfoil-tools.com and downloads each airfoil to data/scrape folder.

### Requirements
- bs4: Beautiful soup

---
**NOTE**

This may not work if airfoil-tools changes their website.

---

## Step2_XfoilScrapedData.py
This file processes the airfoils in data/scrape folder. **This code is intended to be run on ubuntu.** It will loop through each of the files and run the xfoil simulation gathering data on Cl, Cd, Cdp, Cm, and Cp distribution for each angle of attack. The results are then interpolated such that every airfoil has the same number of points for the geometry as well as for the Cp distribution. The `pchip` method is used to interpolate the data.

The results from Step2_XfoilScrapedData.py are saved to json/ folder.

## Step3_NormalizeData.py
After processing all the scraped airfoils into json. The data needs to be normalized so that each of the values `alpha`, `Re`, `NCrit` are of the same scale from 0 to 1 for example. Normalizing is done in 2 ways. First method uses `StandardScaler` which normalizes the data with mean and standard deviation. This is probably the most ideal if you think there maybe some extremes such as `Cp` is very high for a particular airfoil at a certain point. The second method is called `minmax` this normalizes all the data between 0 and 1. This method is ideal if you truely know all your data is of a certain range and there are no extremes.

This file creates a scalers.pickle file with all the normization parameters to do either the `StandardScaler` or `minmax`

## Step4_CreateDataset.py
This takes the normalization file `scalers.pickle` and normalizes all the jsons then saves the results to `datasets/` folder.

### What is inside the datasets folder?
Inside you will see the following
- dnn_scaled_cp_test.pt : Deep Neural Network data format with Cp values for test
- dnn_scaled_cp_train.pt : Deep Neural Network data format with Cp values for train
- dnn_scaled_test.pt : Deep Neural Network data format with only Cl, Cd, Cdp, Cm for test
- dnn_scaled_train.pt : Deep Neural Network data format with only Cl, Cd, Cdp, Cm for train
- graph_scaled_cp_test.pt : Graph Neural Network data format with Cp values for test
- graph_scaled_cp_train.pt : Graph Neural Network data format with Cp values for train
- graph_scaled_test.pt : Graph Neural Network data format with only Cl, Cd, Cdp, Cm for test
- graph_scaled_train.pt : Graph Neural Network data format with only Cl, Cd, Cdp, Cm for train

## view_data.py
This file does 2 things.
1. It reads a all json generated by Step2 and plots is used to plot the max bounds of y/c
![](airfoil_max_bounds.png)


2. It picks a random airfoil and plots the results
![](random_airfoil.png)
46 changes: 46 additions & 0 deletions generate_xfoil/ResizeCp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
''''
Reads through all the Json files and resizes the Cp. Writes the data back to a separate json_cp_resize folder
'''
import os, glob
import os.path as osp
from libs.utils import pchip
import json
from tqdm import trange
import numpy as np
import copy

new_save_dir = 'json_cp_resize'
os.makedirs(new_save_dir,exist_ok=True)

cp_points = 50

x_cp = np.linspace(0,1,cp_points)
data_files = glob.glob(osp.join('json','*.json'))
pbar = trange(len(data_files),desc='Processing')
for i in pbar:
filename = data_files[i]
with open(filename,'r') as f:
airfoil = json.load(f)
new_airfoil = copy.deepcopy(airfoil)

xss = airfoil['xss']
yss = airfoil['yss']

xps = airfoil['xps']
yps = airfoil['yps']

for p in range(len(airfoil['polars'])):
polar = airfoil['polars'][p]

Cp_ss = np.array(polar['Cp_ss'])
Cp_ps = np.array(polar['Cp_ps'])

# Resize cp
Cp_ss = pchip(xss,Cp_ss,x_cp) # from 0 to 1
Cp_ps = pchip(xps,Cp_ps,x_cp) # use xss here because we need same length for cp

new_airfoil['polars'][p]['Cp_ss'] = Cp_ss.tolist()
new_airfoil['polars'][p]['Cp_ps'] = Cp_ps.tolist()

with open(osp.join(new_save_dir,osp.basename(filename)),'w') as f2:
json.dump(new_airfoil,f2)
Loading

0 comments on commit c88636a

Please sign in to comment.