Aerodynamic Shape Optimiser
Status: in development · runs end to end today · source: projectneodrive/aero-drag-tool
Given an STL describing the volume that must fit inside (people, cargo, wheels, mechanism), search for the enclosure shape that minimises drag area.

A shape run: the imported payload in orange, the single closed shell the tool derived around it in blue. The right-hand panel reports the frontal area that actually sets drag, the closing radius that merged three separate bodies into one, and whether the shell still encloses the payload.
Why this tool
Chapter 5 makes the case that above 20–30 km/h aerodynamic drag already dominates rolling resistance, and that shape and frontal area matter more than powertrain efficiency for a vehicle in this class. Solver exist but are not easy to use. The goal is to provide a tool that will both compute the drag force on an existing vehicle and given everything that must fit inside, what is the lowest-drag skin that contains it?
Automotive CFD workflows assume a styling department, a wind tunnel, and a shape that is already roughly decided. What we need is closer to the inverse: the interior volume is the hard constraint (a human being does not compress, and Designing for Humans forbids us from squeezing them to win a drag number), and the shape should follow from it rather than the other way around.
What the tool does
The code lives at github.com/projectneodrive/aero-drag-tool. It is a Python tool with a browser GUI (FastAPI + three.js) and a command line, and it drives real CFD underneath rather than a correlation: OpenFOAM 13 and SU2 are both wired in, and running the same case through both is the cheapest cross-check we have on our own numbers. Solvers ship as containers, so docker compose up web is the whole install.
The loop is:
- Import the payload as an STL — the volume that must fit inside — and set wind speed, ride height and attitude.
- Solve the baseline. Drag force and drag coefficient over a speed range, with Cd·A as the headline. Frontal area is measured by rasterising the silhouette and taking the union, so non-convex shapes and gaps between bodies are counted honestly instead of being smoothed over by a convex hull.
- Derive a fairing. The payload is wrapped in a single closed shell by an anisotropic morphological closing, stretched along the flow direction. A sweep finds the smallest closing radius that merges the payload into one body and builds there — every millimetre past that point is frontal area bought for nothing. Nose and tail taper are optional and adjustable.
- Solve the shell and compare. The shell opens as its own run; the headline tile reports its drag area and the change against the run it came from.
Taper angles can be left to a heuristic, which shapes by rule in seconds, or handed to the true loop, which flies candidate shells through the solver and searches for the nose and tail angles this particular payload actually wants — rather than the ones a textbook assumes.

A solved baseline. The tool checks the Reynolds range before it trusts a single solve: where the range crosses the transitional band, Cd is not constant and scaling one solve as V² would misreport the ends of the curve, so it runs a speed sweep instead.
What it does not do yet
- Wheels in motion are not modelled. Wheels are static geometry sitting in the flow — no rotating wall, no moving ground plane. That is a real omission for a road vehicle, and the biggest one on the list.
- One closed shell only. No separate pods, no open wheel arches.
- CPU only, and meshing is serial, so a fine case is a coffee break rather than a click.
- The SU2 path is incompressible RANS, which is fine at our speeds but not a general-purpose second opinion.
Why it is worth publishing on its own
This is one of the tools here that are useful to other teams immediately, without waiting for a finished Neodrive vehicle. Anyone building an enclosed light vehicle faces the same problem. If you have people in your team to do theses kind of computation, come chat. A working, documented, open version of this is a contribution to the category in its own right, and it costs us nothing to share.
Open questions
- How well does the predicted drag match reality, and against what reference?
- Does the optimiser produce shapes that are actually manufacturable, or only mathematically optimal?
- How much drag are we willing to trade for entry, exit, and visibility?