airfoil_cst_rans_mlp

Ensemble of 5 MLPs (8 -> 96 -> 96 -> 96 -> 3, SiLU, bootstrap) mapping a 6-weight CST airfoil and the angle of attack to lift, drag and quarter-chord moment coefficients of a fully turbulent, incompressible 2-D RANS solution at Re = 4e6. The ensemble spread is returned as an uncertainty.

airfoil_cst_rans_mlp v1.0.0 (revision v1.0.0.post1) Β· part of the PINNeAPPle zoo Β· training data PINNeAPPle-Labs/airfoil-rans-cst-re4e6

Try it without installing anything: PINNeAPPle zoo demo (pick airfoil_cst_rans_mlp: its predictions along each input with their band and where its physics checks warn or fail, and your own inputs evaluated in the browser).

Task: Airfoil aerodynamic coefficients (Cl, Cd, Cm) from shape and angle of attack, 2-D steady RANS

Inputs

Name Unit Description
T0 - CST thickness weight, leading edge
T1 - CST thickness weight, mid chord
T2 - CST thickness weight, aft
M0 - CST camber weight, front
M1 - CST camber weight, mid chord
M2 - CST camber weight, aft
alpha_deg deg angle of attack

Outputs

Name Unit Description
Cl - lift coefficient (per unit span, chord 1)
Cd - drag coefficient
Cm - pitching-moment coefficient about c/4

Validity range

  • T0: [0.1, 0.24]
  • T1: [0.08, 0.22]
  • T2: [0.08, 0.22]
  • M0: [-0.03, 0.08]
  • M1: [-0.02, 0.14]
  • M2: [-0.04, 0.12]
  • alpha_deg: [-2.0, 14.0]
  • reynolds: 4000000.0
  • mach: incompressible
  • geometry_family: 2nd-order Bernstein CST, upper = M + T, lower = M - T, trailing-edge thickness 0.25 % chord
  • regime: fully turbulent (k-omega SST), attached to mildly separated; deep stall (Cl swing > 0.1 over the last 500 iterations) was excluded from training

Known limitations

  • Drag at high lift reads ~14 % high on the campaign grid (20k cells) compared with finer grids/XFOIL; the surrogate inherits the solver's bias, it does not correct it.
  • Not valid in deep stall, at other Reynolds numbers, compressible flow or outside the CST bounds.
  • Accuracy is against the same solver and grid that generated the training data (interpolation error); the solver's own error against experiment is the larger term.

Architecture

  • MLPEnsemble β€” {"k": 5, "width": 96, "in_dim": 8, "out_dim": 3, "activation": "SiLU", "targets": ["Cl", "log Cd", "Cm"]}

Physics

  • steady incompressible RANS, k-omega SST (OpenFOAM v1912 simpleFoam)

Validation

Reference: Held-out OpenFOAM RANS runs on 15 airfoil shapes never seen in training (60 runs) and 36 NACA 0012/2412/4412/4415 runs excluded from training. The solver is verified: 3-grid study on NACA 2412 at alpha 4 deg (Cd GCI 1.9 %, observed order 2.4; Cl within 0.02 %), XFOIL 6.99 tripped (Cl -2.3 %, Cd +4.5 %), lift slope 0.110/deg vs 0.110/deg thin-airfoil theory, NASA TMR NACA 0012 SST (Cd 0.00812 vs 0.0081).

Metric Value
test/Cl_mae 0.0028476635807695894
test/Cl_max_abs 0.019326576151895702
test/Cd_mae 9.115975415693806e-05
test/Cd_max_abs 0.0011104396736285153
test/Cd_mape_pct 0.5447462642571239
test/Cd_p90_pct 1.0353616187191836
test/Cm_mae 0.0004539437796155409
test/Cm_max_abs 0.0025451080196258954
test/n 60.0
naca_reference/Cl_mae 0.003231396365459536
naca_reference/Cl_max_abs 0.028683417593309724
naca_reference/Cd_mae 0.00013511379859050402
naca_reference/Cd_max_abs 0.0013729081470662922
naca_reference/Cd_mape_pct 0.615631882294239
naca_reference/Cd_p90_pct 1.1373013614073955
naca_reference/Cm_mae 0.00022242696868302747
naca_reference/Cm_max_abs 0.0019696524520329602
naca_reference/n 36.0
xfoil_naca2412/Cl_mae 0.010092481383557984
xfoil_naca2412/Cl_max_abs 0.02017109433227715
xfoil_naca2412/Cd_mae 0.00028128564747221293
xfoil_naca2412/Cd_max_abs 0.0009061347505152015
xfoil_naca2412/Cd_mape_pct 2.812720929821659
xfoil_naca2412/Cd_p90_pct 6.872440265354455
xfoil_naca2412/Cm_mae 0.0009800236757100693
xfoil_naca2412/Cm_max_abs 0.0012370981942770864
xfoil_naca2412/n 9.0

Trust

Decision: APPROVED Β· score 1.00 Β· coverage 100%

Training data

  • dataset: airfoil_rans_cst_re4e6
  • split: by shape (seed 3, 15 % of LHS shapes held out)
  • source: examples/handoff_cases/airfoil_ld (campaign), apps/aero_optimizer/model/surrogate.pt

License: apache-2.0

Citation

PINNeAPPle contributors (2026). Airfoil RANS campaign (OpenFOAM v1912 simpleFoam, k-omega SST, Re 4e6, 436 runs) and MLP-ensemble surrogate. PINNeAPPle model zoo, https://github.com/PINNeAPPle-Labs/PINNeAPPle

Physics validation

warn: data finite (missing values documented) (19/20 applicable checks pass; level standard; generated by pp.validate with PINNeAPPle 0.7.0, schema validation-report/v1).

Factor Credibility Meaning
code_verification 0 no evidence
solution_verification 3 passes quantitative checks
validation 4 passes against an independent reference or a guaranteed bound
input_pedigree 2 passes with warnings or qualitative evidence only
uncertainty 2 passes with warnings or qualitative evidence only
robustness 0 no evidence
applicability 0 no evidence
Check Status Result
method.status not-applicable no catalog method id given (validate(..., method='S2'))
reference.card_metrics pass card metrics reproduced on the stored reference (max relative difference)
reference.acceptance.test/Cl_mae pass held-out test/Cl_mae within the zoo acceptance limit
reference.acceptance.test/Cd_mape_pct pass held-out test/Cd_mape_pct within the zoo acceptance limit
reference.acceptance.test/Cm_mae pass held-out test/Cm_mae within the zoo acceptance limit
reference.acceptance.naca_reference/Cl_mae pass held-out naca_reference/Cl_mae within the zoo acceptance limit
reference.acceptance.naca_reference/Cd_mape_pct pass held-out naca_reference/Cd_mape_pct within the zoo acceptance limit
physics.model_checks.1 pass lift slope vs thin-airfoil 2 pi/rad (alpha -2..6, held-out shapes)
physics.model_checks.2 pass Cl increases with alpha below stall (alpha -2..10, held-out shapes)
physics.model_checks.3 pass symmetric airfoil: /Cl(0)/ and /Cl(2)+Cl(-2)/ (NACA 0012)
physics.model_checks.4 pass Cd > 0 and finite outputs on 2000 random in-range inputs
applicability.range not-applicable no query inputs given
uncertainty.spread pass the model returns a predictive spread or bound
metamorphic.symmetry.camber-mirror-lift pass worst violation 0.819 over 64 samples
metamorphic.symmetry.camber-mirror-moment pass worst violation 1.03 over 64 samples
metamorphic.symmetry.camber-mirror-drag pass worst violation 0.0219 over 64 samples
metamorphic.monotonicity.lift-grows-with-alpha pass worst violation 0 over 64 samples
data.finite warn stored audit card of airfoil_rans_cst_re4e6: missing values (NaN) in train/Cm (340, documented)
data.physics.physics not-applicable stored audit card of airfoil_rans_cst_re4e6: no PDE stated for this dataset
data.physics.constraint.cd-0 pass stored audit card of airfoil_rans_cst_re4e6: Cd > 0: 0 of 448 rows violate it
data.diversity.duplicates pass stored audit card of airfoil_rans_cst_re4e6: train: 0 exact, 0 near copies of 340; test: 0 exact, 0 near copies of 60
data.diversity.effective pass stored audit card of airfoil_rans_cst_re4e6: effective sample count 6.47 of 340 (no generator stated: only a collapse to one pattern is flagged)
data.leakage pass stored audit card of airfoil_rans_cst_re4e6: 0 of 60 test samples are (near) copies of train samples (closest: 1.03 x the median train spacing)

Model SHA-256 fb3de764d06bc4194dd6e92120dc5f76a3db15c4a71501a17c8c1599345e7333.

How to use

pip install "pinneapple @ git+https://github.com/PINNeAPPle-Labs/PINNeAPPle"
import pinneapple as pp

model = pp.zoo.load("airfoil_cst_rans_mlp")          # weights checked against their SHA-256
inputs = {"T0": 0.235519, "T1": 0.215361, "T2": 0.195097, "M0": 0.058294, "M1": 0.016703, "M2": 0.09483, "alpha_deg": 0.810289}
out = model.predict(inputs)                 # warns for inputs outside the validity range
print({k: round(float(v[0]), 6) for k, v in out.items()})
# {'Cl': 0.316984, 'Cd': 0.010137, 'Cm': -0.042694, 'Cl_std': 0.002746, 'Cd_std': 2.3e-05, 'Cm_std': 0.000136, 'LD': 31.270027, 'LD_std': 0.270385}
print(pp.zoo.query_checks(model, inputs)[0]["verdict"]["status"])   # per-query trust checks
# pass
print(pp.zoo.validate(model).decisao)        # card metrics reproduced + physics checks
# APPROVED

The inputs are the first held-out test case of the training dataset; its reference value is Cl = 0.317408, Cd = 0.0101194, Cm = -0.0426839. pp.zoo.evaluate("airfoil_cst_rans_mlp") recomputes every metric of the card on the stored reference.

Hosted inference

No Hugging Face inference provider can run this model, so the Hub widget is off (inference: false). It is a small PyTorch network, but its prediction is more than a forward pass: the inputs are encoded and normalised, the outputs denormalised (and, for ensembles, averaged with their spread), and every query is checked against the validity range and the model's physics checks. The pinneapple library does all of that (below); the ONNX graph carries the pre- and post-processing but not the checks; the zoo demo Space shows the model along a sweep of each input and runs it, with its checks, in your browser.

ONNX

model.onnx (opset 17) maps x, shape (n, 7) float32 with the columns T0, T1, T2, M0, M1, M2, alpha_deg, to the outputs mean: ['Cl', 'Cd', 'Cm']; std: ['Cl_std', 'Cd_std', 'Cm_std']; ld: ['LD', 'LD_std']. Pre- and post-processing are in the graph (largest difference from PyTorch on the reference inputs: 5.3e-07); the validity-range and physics checks are not, so check the range yourself.

import numpy as np, onnxruntime as ort
from huggingface_hub import hf_hub_download

path = hf_hub_download("PINNeAPPle-Labs/airfoil-cst-rans-mlp", "model.onnx", revision="v1.0.0.post1")
session = ort.InferenceSession(path)
x = np.array([[0.235519, 0.215361, 0.195097, 0.058294, 0.016703, 0.09483, 0.810289]], np.float32)
print(dict(zip([o.name for o in session.get_outputs()], session.run(None, {"x": x}))))

Files

File Content SHA-256
weights.pt PyTorch state_dict (torch.load(weights_only=True)), what pp.zoo.load reads ff223aab60cbade5eb711e565a90e86e69fe7a65e59e7e7d08be256828a898be
config.json architecture and normalisation 6d7d66c9d8d3e90f7b3480210b757d24d23bc5394c7f9d2d7bab08792608a093
model_card.json the model card: inputs, outputs, validity range, metrics, trust report c3257991339ecf1604d64cc621ae21a0e26e0cd65e74f23e7f6fe166d0300a34
model.safetensors the same tensors as weights.pt in safetensors format (pinneapple_hub.zoo.export.load_safetensors loads them) derived
model.onnx ONNX graph, physical inputs to physical outputs (below) derived
example.json the "How to use" case: inputs, outputs, reference, verdicts derived

The SHA-256 are those of the package's manifest: pp.zoo.load refuses any other file.

Cite

If you use this model, please cite PINNeAPPle (software, Zenodo DOI 10.5281/zenodo.23343062; see CITATION.cff):

@software{pinneapple,
  author = {Barros, Yan and Schiassi, Enrico},
  title  = {PINNeAPPle},
  doi    = {10.5281/zenodo.23343062},
  url    = {https://github.com/PINNeAPPle-Labs/PINNeAPPle}
}
Downloads last month
155
Safetensors
Model size
98.9k params
Tensor type
F32
Β·
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Dataset used to train PINNeAPPle-Labs/airfoil-cst-rans-mlp

Space using PINNeAPPle-Labs/airfoil-cst-rans-mlp 1