Upload folder using huggingface_hub
Browse files- README.md +29 -0
- airfoil_vocab.json +12 -0
- best.pt +3 -0
- config.json +58 -0
- feature_names.json +23 -0
- inference.py +57 -0
- last.pt +3 -0
- predicted_max_cl_b707b_fixed.stl +0 -0
- predicted_min_cd_b707b_fixed.stl +0 -0
- prediction_max_cl_b707b_fixed.json +10 -0
- prediction_min_cd_b707b_fixed.json +10 -0
README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
library_name: pytorch
|
| 3 |
+
tags:
|
| 4 |
+
- tabular
|
| 5 |
+
- pytorch
|
| 6 |
+
- classification
|
| 7 |
+
- aviation
|
| 8 |
+
- wing-design
|
| 9 |
+
datasets:
|
| 10 |
+
- ecopus/transport-wings-500
|
| 11 |
+
license: mit
|
| 12 |
+
---
|
| 13 |
+
|
| 14 |
+
# Wing Selector MLP
|
| 15 |
+
|
| 16 |
+
This repository contains a PyTorch MLP that scores aircraft-style wings **within the same airfoil** for a chosen objective:
|
| 17 |
+
- **min_cd** (minimize drag),
|
| 18 |
+
- **max_cl** (maximize lift),
|
| 19 |
+
- **max_ld** (maximize lift-to-drag).
|
| 20 |
+
|
| 21 |
+
It was trained on the dataset **[ecopus/transport-wings-500](https://huggingface.co/datasets/ecopus/transport-wings-500)**.
|
| 22 |
+
|
| 23 |
+
## Files
|
| 24 |
+
- `best.pt` – best checkpoint by validation top-1@group
|
| 25 |
+
- `last.pt` – final checkpoint after training
|
| 26 |
+
- `config.json` – input dim, #airfoils, feature scaler stats
|
| 27 |
+
- `feature_names.json` – expected feature order
|
| 28 |
+
- `airfoil_vocab.json` – airfoil name → id mapping used during training
|
| 29 |
+
- `inference.py` – minimal loader & scoring helper
|
airfoil_vocab.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"atr72sm_fixed": 0,
|
| 3 |
+
"b707a_fixed": 1,
|
| 4 |
+
"b707b_fixed": 2,
|
| 5 |
+
"b707c_fixed": 3,
|
| 6 |
+
"b707d_fixed": 4,
|
| 7 |
+
"b707e_fixed": 5,
|
| 8 |
+
"b737a_fixed": 6,
|
| 9 |
+
"b737c_fixed": 7,
|
| 10 |
+
"sc20612_fixed": 8,
|
| 11 |
+
"sc20714_fixed": 9
|
| 12 |
+
}
|
best.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c518975bc78802090eba638d3a9ffc94b2cba174e08b52cc43de3973f507ea65
|
| 3 |
+
size 86755
|
config.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"in_dim": 21,
|
| 3 |
+
"n_airfoils": 10,
|
| 4 |
+
"feat_stats": {
|
| 5 |
+
"means": [
|
| 6 |
+
2.2974946202834445,
|
| 7 |
+
0.6872147750606139,
|
| 8 |
+
0.2578163856764634,
|
| 9 |
+
0.37480359852313994,
|
| 10 |
+
2.3189779766400656,
|
| 11 |
+
9.467880272467932,
|
| 12 |
+
1.0870784179866313,
|
| 13 |
+
0.5000662527711445,
|
| 14 |
+
0.1509065439546441,
|
| 15 |
+
0.5227734553565582,
|
| 16 |
+
0.6186037808159988,
|
| 17 |
+
0.41770886595050494,
|
| 18 |
+
-1.5537850901646153,
|
| 19 |
+
1.4478309332036345,
|
| 20 |
+
-3.993618442217509,
|
| 21 |
+
1.7111458281675975,
|
| 22 |
+
0.0070095833313340945,
|
| 23 |
+
113.27690156300862,
|
| 24 |
+
6.605367994308471,
|
| 25 |
+
-1.7461201533675195,
|
| 26 |
+
1.0
|
| 27 |
+
],
|
| 28 |
+
"stds": [
|
| 29 |
+
0.4446350828425311,
|
| 30 |
+
0.13155030403161297,
|
| 31 |
+
0.07064456938056878,
|
| 32 |
+
0.07191935098350889,
|
| 33 |
+
0.632331195206683,
|
| 34 |
+
2.6987141911651236,
|
| 35 |
+
0.20895228281937822,
|
| 36 |
+
0.09680051733887858,
|
| 37 |
+
0.029613501772416416,
|
| 38 |
+
0.10120953118257814,
|
| 39 |
+
0.11874387208280242,
|
| 40 |
+
0.08241397400630304,
|
| 41 |
+
0.6453231247887586,
|
| 42 |
+
0.3816419414156409,
|
| 43 |
+
1.1807503216075736,
|
| 44 |
+
0.19466236480543672,
|
| 45 |
+
0.0007977911059154624,
|
| 46 |
+
11.519966166557653,
|
| 47 |
+
0.24553951235854007,
|
| 48 |
+
1.3978423603895884,
|
| 49 |
+
1.0
|
| 50 |
+
]
|
| 51 |
+
},
|
| 52 |
+
"objectives": [
|
| 53 |
+
"min_cd",
|
| 54 |
+
"max_cl",
|
| 55 |
+
"max_ld"
|
| 56 |
+
],
|
| 57 |
+
"framework": "pytorch"
|
| 58 |
+
}
|
feature_names.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
"span_m",
|
| 3 |
+
"root_chord_m",
|
| 4 |
+
"tip_chord_m",
|
| 5 |
+
"taper",
|
| 6 |
+
"area_m2",
|
| 7 |
+
"aspect_ratio",
|
| 8 |
+
"mac_m",
|
| 9 |
+
"chord_mean",
|
| 10 |
+
"chord_std",
|
| 11 |
+
"chord_mid",
|
| 12 |
+
"chord_q1",
|
| 13 |
+
"chord_q3",
|
| 14 |
+
"twist_mean",
|
| 15 |
+
"twist_std",
|
| 16 |
+
"washout_deg",
|
| 17 |
+
"cl_max",
|
| 18 |
+
"cd_min",
|
| 19 |
+
"ld_max",
|
| 20 |
+
"cla_per_rad",
|
| 21 |
+
"alpha0l_deg",
|
| 22 |
+
"has_polar"
|
| 23 |
+
]
|
inference.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import os, json, numpy as np, torch, torch.nn as nn
|
| 3 |
+
|
| 4 |
+
OBJECTIVES = ["min_cd", "max_cl", "max_ld"]
|
| 5 |
+
|
| 6 |
+
class MLPSelector(nn.Module):
|
| 7 |
+
def __init__(self, in_dim:int, n_airfoils:int, obj_dim:int=3, af_embed_dim:int=8, hidden:int=128):
|
| 8 |
+
super().__init__()
|
| 9 |
+
self.af_emb = nn.Embedding(n_airfoils, af_embed_dim)
|
| 10 |
+
self.net = nn.Sequential(
|
| 11 |
+
nn.Linear(in_dim + obj_dim + af_embed_dim, hidden),
|
| 12 |
+
nn.ReLU(),
|
| 13 |
+
nn.Linear(hidden, hidden),
|
| 14 |
+
nn.ReLU(),
|
| 15 |
+
nn.Linear(hidden, 1),
|
| 16 |
+
)
|
| 17 |
+
def forward(self, x, obj_id, af_id):
|
| 18 |
+
B = x.size(0)
|
| 19 |
+
obj_oh = torch.zeros(B, 3, device=x.device)
|
| 20 |
+
obj_oh[torch.arange(B), obj_id] = 1.0
|
| 21 |
+
af_e = self.af_emb(af_id)
|
| 22 |
+
z = torch.cat([x, obj_oh, af_e], dim=1)
|
| 23 |
+
return self.net(z).squeeze(1)
|
| 24 |
+
|
| 25 |
+
def load_selector(local_dir=".", device="cpu"):
|
| 26 |
+
ckpt_path = os.path.join(local_dir, "best.pt")
|
| 27 |
+
if not os.path.exists(ckpt_path):
|
| 28 |
+
ckpt_path = os.path.join(local_dir, "last.pt")
|
| 29 |
+
if not os.path.exists(ckpt_path):
|
| 30 |
+
raise FileNotFoundError("best.pt/last.pt not found in "+local_dir)
|
| 31 |
+
|
| 32 |
+
ckpt = torch.load(ckpt_path, map_location=device)
|
| 33 |
+
cfg = {
|
| 34 |
+
"in_dim": int(ckpt["in_dim"]),
|
| 35 |
+
"n_airfoils": int(ckpt["n_airfoils"]),
|
| 36 |
+
"feat_stats": {
|
| 37 |
+
"means": np.array(ckpt["feat_stats"]["means"], dtype=np.float32),
|
| 38 |
+
"stds": np.array(ckpt["feat_stats"]["stds"], dtype=np.float32),
|
| 39 |
+
}
|
| 40 |
+
}
|
| 41 |
+
model = MLPSelector(cfg["in_dim"], cfg["n_airfoils"])
|
| 42 |
+
model.load_state_dict(ckpt["model"])
|
| 43 |
+
model.to(device).eval()
|
| 44 |
+
return model, cfg
|
| 45 |
+
|
| 46 |
+
def standardize(X_raw: np.ndarray, means: np.ndarray, stds: np.ndarray) -> np.ndarray:
|
| 47 |
+
X_imp = np.where(np.isfinite(X_raw), X_raw, means)
|
| 48 |
+
return (X_imp - means) / np.where(stds==0, 1.0, stds)
|
| 49 |
+
|
| 50 |
+
def score_wings(model, X_std: np.ndarray, airfoil_id: int, objective: str, device="cpu"):
|
| 51 |
+
obj_id = OBJECTIVES.index(objective)
|
| 52 |
+
X = torch.tensor(X_std, dtype=torch.float32, device=device)
|
| 53 |
+
obj_ids = torch.full((X.size(0),), obj_id, dtype=torch.long, device=device)
|
| 54 |
+
af_ids = torch.full((X.size(0),), airfoil_id, dtype=torch.long, device=device)
|
| 55 |
+
with torch.no_grad():
|
| 56 |
+
probs = torch.sigmoid(model(X, obj_ids, af_ids)).cpu().numpy()
|
| 57 |
+
return probs # higher = better
|
last.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c319f9257b5b4e4b6c2fe803ef769ab5d374c2761a5ff86009e8c24f8c2f52e7
|
| 3 |
+
size 86755
|
predicted_max_cl_b707b_fixed.stl
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
predicted_min_cd_b707b_fixed.stl
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
prediction_max_cl_b707b_fixed.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"objective": "max_cl",
|
| 3 |
+
"airfoil": "b707b_fixed",
|
| 4 |
+
"predicted_wing_id": "wing_0373",
|
| 5 |
+
"pred_prob": 0.9353432059288025,
|
| 6 |
+
"span_m": 2.4116458892822266,
|
| 7 |
+
"root_chord_m": 0.911438524723053,
|
| 8 |
+
"tip_chord_m": 0.4535040259361267,
|
| 9 |
+
"taper": 0.4975695312023163
|
| 10 |
+
}
|
prediction_min_cd_b707b_fixed.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"objective": "min_cd",
|
| 3 |
+
"airfoil": "b707b_fixed",
|
| 4 |
+
"predicted_wing_id": "wing_0003",
|
| 5 |
+
"pred_prob": 0.934077262878418,
|
| 6 |
+
"span_m": 2.0890963077545166,
|
| 7 |
+
"root_chord_m": 0.880916953086853,
|
| 8 |
+
"tip_chord_m": 0.3620271682739258,
|
| 9 |
+
"taper": 0.41096627712249756
|
| 10 |
+
}
|