Open-source project
peterdsharpe/NeuralFoil avatar
peterdsharpe/NeuralFoil

A NumPy airfoil surrogate that reports its own uncertainty

NeuralFoil is a practical airfoil aerodynamics analysis tool using physics-informed machine learning, exposed to end-users in pure Python/NumPy.

485 stars59 forksPythonMIT

At a glance

What is it?
A physics-informed surrogate for XFoil, trained in PyTorch on nearly eight million runs and executed in pure NumPy, with eight model sizes and an analysis_confidence output that flags where it does not trust itself. The speed and accuracy figures are the project's own claims, and the figures behind them are images.
Who is it for?
Adopt NeuralFoil for design loops that call an aerodynamics solver thousands of times, since the differentiability and the guarantee of a returned answer are what a gradient-based optimiser needs and what an inviscid panel method will not give you. Do not adopt it where you need certification-grade fidelity to a validated method, because the accuracy claim is a few percent against XFoil, and XFoil itself is the thing being approximated.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Trained in PyTorch, run in NumPy, and it depends on AeroSandbox anyway

The deployment story is the first thing the README establishes. NeuralFoil is available as a pure Python and NumPy standalone, trained in PyTorch and runtime-executed in NumPy.

That split is the whole trick for adoption. A surrogate trained in a deep learning framework does not need that framework at inference if the learned weights are small enough to evaluate directly, and a NumPy evaluation has no GPU, no CUDA version and no autograd graph to manage.

The dependency list complicates the word standalone:

toml
dependencies = [
    "numpy>=1.26",
    "aerosandbox>=4.2.7,<4.3.0",
]

AeroSandbox is a runtime requirement, not an optional extra. The comments above it explain why the range is so narrow: 4.2.7 is the first AeroSandbox release compatible with NeuralFoil 0.3.x, earlier releases pin neuralfoil below 0.3.0, and the upper bound exists because the two packages co-evolve.

So installing NeuralFoil pulls in AeroSandbox, and the version you get is constrained in both directions by a package you did not ask for. Anyone managing a pinned environment has to reconcile those constraints rather than adding one library.

The upside is that AeroSandbox is where the extended features live, including transonics, post-stall and control surface deflections, so the dependency is not arbitrary.

Eight sizes from xxsmall to xxxxlarge, and you pick the tradeoff

NeuralFoil ships eight neural network models with increasing levels of complexity, named "xxsmall", "xsmall", "small", "medium", "large", "xlarge", "xxlarge" and "xxxlarge".

The README describes this spectrum as a tradeoff between accuracy and computational cost, and the naming makes the only variable you need to set at the call site. In the usage example the size is passed as `model_size="xlarge"`, described as optional.

The double-x prefix appears at both ends of the range, which is unusual and worth reading carefully. There is a "xxsmall" and an "xxxlarge", so the ordering is lexical in a way that does not quite match intuition, and someone picking by name has to be more careful than the labels suggest.

Eight points on a cost curve is a reasonable spread for an embedded surrogate. A single size would force one of two bad defaults: pick the largest and waste the speed advantage on work that does not need the accuracy, or pick the smallest and discover the accuracy loss in a result nobody checked.

Because the runtime is NumPy and the network is small, the per-call cost of the larger models is still small enough that the speed advantage over XFoil survives at the top of the range, which is the claim the size spectrum exists to support.

analysis_confidence is the output a surrogate usually leaves out

The feature the README singles out as unique is that NeuralFoil assesses its own trustworthiness, yielding an `analysis_confidence` output. Queries where the flow is sensitive or strongly out of distribution are flagged.

This matters more than a typical accuracy claim, because a surrogate that is wrong everywhere is easy to detect and a surrogate that is wrong in one region is not. Confidence output turns that second failure mode into something a caller can act on.

The README is specific about where it is most useful: design optimization, where constraining the uncertainty metric keeps designs stable under small changes in shape and flow conditions.

That is a different use from error bars on a plot. In an optimisation loop, constraining the metric changes what the optimiser searches for, so the optimiser stops exploiting regions where the model happens to be confident and wrong. A design that only performs well inside the model's confident region fails the moment the flow moves, which is the situation that constraint exists to prevent.

The output is also described as a measure of uncertainty and is used the same way in the accuracy section, where the same polar is replotted coloured by confidence so that regions with delicate or uncertain aerodynamic behaviour are visible.

The README does not say how the metric is calibrated, so it should be read as a relative indicator across a sweep rather than an absolute probability that any given answer is right.

Guaranteed to return an answer, which is the point

The headline properties are stated compactly in the opening, and each one answers a specific failure of the tool it approximates.

Guaranteed to return an answer, with no non-convergence issues. Vectorized. And C-infinity-continuous, which the README flags as critical for gradient-based optimization.

These are three claims about the same underlying property. A panel-method solver like XFoil is a numerical flow solution with iterative convergence, so it can fail to converge, and when it does you get a jagged answer in the region where it struggled. A learned surrogate evaluated in closed form either returns a value or does not, and if the architecture embeds the physics the function it returns is smooth by construction.

That smoothness is the one that pays off in optimisation. A gradient-based optimiser needs a derivative, and a surrogate whose value function is continuous gives finite-difference or automatic gradients that behave, where a non-converged panel solution gives noise the optimiser will chase.

The extended features add the rest: viscous, compressible aerodynamics for nearly any airfoil, with control surface deflections, across 360 degrees of angle of attack, at any Reynolds number, in roughly 5 milliseconds.

For aerodynamics specialists there is also fine-grained boundary layer control, with critical Reynolds number and forced trips, plus boundary layer thickness, shape factor, edge velocity ratio and pressure distributions.

It smooths the jag where XFoil stalls out near CL 1.4

The accuracy argument is made two ways, and the second one is the more interesting.

The first is that NeuralFoil tracks XFoil closely across a wide range of angle of attack and Reynolds number, accurate to within a few percent. The demonstration airfoil is described as having been developed from scratch for a real-world aircraft development program and as completely separate from the airfoils used in training, so the claim is that the model is not recalling this shape. The README says so directly, that NeuralFoil is not cheating by memorising the airfoil's performance.

That is a well-constructed out-of-sample check, and the note that airfoils closer to the training set will do even better is the right caveat to attach to it.

The second argument is about where the two disagree. NeuralFoil is described as smoothing out XFoil's jagged predictions, with the specific example given being near a lift coefficient of 1.4 at a Reynolds number of 80k, in cases where XFoil is not reliably converging.

That is a claim about the region where the reference solution is untrustworthy. Disagreeing with a converged answer is a problem; disagreeing smoothly where the other tool was failing is a feature, and it is the reason an optimiser can use the surrogate instead of the panel method.

The generalisation claim that follows is the strongest one in the README: because domain knowledge is embedded in the architecture, the model can accurately predict airfoils with extreme control surface deflections even though no training sample has a deflected control surface.

The figures themselves are images, so none of these numbers can be checked from the text.

Training dependencies live in dependency-groups, not in extras

The packaging file makes a decision that more projects could copy.

Consumer extras carry only what a user of the published package needs, which for tests means pytest and nbval. The training and documentation dependencies live under a separate dependency-groups table instead, with the comment explaining the reason: the training code is not shipped in the wheel and is only usable from a repository checkout.

That is a precise reason, and it has an exact consequence. A user who wants to train a new model cannot do it from the installed package, because the code is not there. Anyone who wants to reproduce the models has to clone the repository.

The distinction between optional dependencies and dependency groups is the difference between something a published artifact declares and something a checkout declares, and putting torch, ray and polars in the second bucket keeps a heavy training stack out of every user install.

Two smaller details in the same file. The build backend is hatchling, and the classifier says Development Status 5 - Production/Stable.

That classifier sits oddly next to a project with no GitHub releases at all and a version of 0.3.3. Stable is a claim about API compatibility, and there is no tag history here to check it against.

The notebook testing dependency deserves a mention too. nbval validates notebooks by executing them, which is how a tutorial stays runnable.

The repository ships the paper, the benchmarks and the studies next to the package

The root layout describes a research project that was packaged rather than a package that was documented.

Alongside `neuralfoil/`, `tests/`, `pyproject.toml` and `uv.lock` there are `training/`, `paper/`, `benchmarking/`, `studies/` and `media/`.

The paper directory is not documentation. It holds the preprint, which the README points to for technical details, validation cases and case studies, and the same PDF is cited as the source of the hybrid formulation. The project page at peterdsharpe.github.io is the author's own, and the arXiv identifier 2503.16323 is linked from the badge row.

The README also states that the figure in it is an excerpt from the author's PhD thesis, which places NeuralFoil in a body of work rather than presenting it as a standalone tool.

The size claim is worth repeating because it is unusual: fewer than 500 lines of user-facing code, with the file named as `neuralfoil/main.py`. For a project with a training pipeline, a distributed training dependency and a paper, that is a very small runtime surface.

Maintenance is easy to date. The last push was on 2026-09-26, the licence file is named `LICENSE.txt` rather than `LICENSE`, and the repository publishes no GitHub releases, so the version in `pyproject.toml` is the only place a number appears.

Editorial conclusion

Adopt NeuralFoil for design loops that call an aerodynamics solver thousands of times, since the differentiability and the guarantee of a returned answer are what a gradient-based optimiser needs and what an inviscid panel method will not give you. Do not adopt it where you need certification-grade fidelity to a validated method, because the accuracy claim is a few percent against XFoil, and XFoil itself is the thing being approximated. Two things to check first: whether the AeroSandbox version your environment already pins is inside the range NeuralFoil allows, since the two co-evolve and the dependency is capped, and whether your workflow can act on analysis_confidence, since an uncertainty output nobody constrains does not make a design hold up under perturbation.

Frequently asked questions

how to use neuralfoil

Install it with pip install neuralfoil, then call an entry point such as get_aero_from_dat_file with a .dat file, or get_aero_from_coordinates with an array of coordinates. Both take angle of attack and Reynolds number, accept a model_size such as xlarge, and are vectorized across both.

How does NeuralFoil compare to XFoil?

The README claims roughly 30x faster for a single analysis and roughly 1000x faster for multipoint analysis, with accuracy typically within a few percent of XFoil. It also claims to smooth out regions where XFoil fails to converge reliably, giving the example near a lift coefficient of 1.4 at a Reynolds number of 80k.

What is the analysis_confidence output in NeuralFoil?

It is NeuralFoil's own uncertainty measure. Queries where the flow is sensitive or strongly out of distribution are flagged, and the README describes constraining it during design optimization as a way to keep designs robust to small changes in shape and flow conditions.

What are the runtime dependencies of NeuralFoil?

numpy at 1.26 or newer, and aerosandbox from 4.2.7 capped below 4.3.0. The pyproject comment explains the cap as the two packages co-evolving, since earlier AeroSandbox releases pin neuralfoil below 0.3.0.

Official sources

  1. Issues
  2. License: MIT
  3. peterdsharpe/NeuralFoil on GitHub
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/peterdsharpe-neuralfoil.svg)](https://hysenlabs.com/projects/peterdsharpe-neuralfoil)