OpenFOAM for DIY Car Aerodynamics: Finding Models and Running Your First CFD Simulation
OpenFOAM for Car Aero: Getting Past the Model Problem
The hardest part of running automotive CFD in OpenFOAM isn’t the solver. It’s finding a clean 3D model to feed it. Most freely available car models are built for visual rendering, not simulation — they have open edges, non-manifold geometry, and interior faces that will crash a mesher on the first attempt.
Where to Find Usable Geometry
GrabCAD is the best starting point. Search the car name plus “body” or “exterior” — you want something representing the outer shell, not a detailed mechanical assembly with every interior component included. Quality ranges from completely unusable to surprisingly clean, and you won’t know which until you open it.
Thingiverse is worth a look too. Models built for 3D printing often skip the cleanup step that rendering models require, because print files need to be watertight by design. Simpler geometry, but often more solver-friendly right out of the box.
If nothing clean turns up, a simplified block model built in FreeCAD is genuinely more useful than a detailed model that won’t mesh. A rough exterior profile capturing the hood slope, roofline, windscreen angle, and trunk is enough to show real flow features. Don’t let perfect geometry be the reason you never run anything.
Preparing the Geometry
Whatever model you source, it needs to become a watertight, manifold STL before snappyHexMesh produces anything sensible. The basic workflow:
- Import into Blender or MeshLab
- Check for non-manifold edges (in Blender: Edit Mode → Select → Select All by Trait → Non Manifold)
- Fill holes, remove interior faces, merge duplicate vertices
- Export as binary STL
MeshLab’s filters under “Cleaning and Repairing” handle a lot of this automatically. For qualitative flow visualization rather than precise drag numbers, the geometry doesn’t need to be perfect — it just needs to be topologically solid.
Setting Up the OpenFOAM Case
For external aerodynamics at road car speeds, simpleFoam is the right solver. Steady-state, incompressible — compressibility effects are negligible well below the speed of sound, so there’s no reason to add that complexity.
The basic case directory structure:
myCarCase/
0/ <-- initial and boundary conditions (U, p, nut, k, epsilon)
constant/ <-- turbulence model settings; STL file goes in triSurface/ here
system/ <-- snappyHexMeshDict, blockMeshDict, controlDict, fvSchemes, fvSolution
The tutorial case at $FOAM_TUTORIALS/incompressible/simpleFoam/motorBike is a near-perfect template. Copy it, swap in your geometry, adjust the domain dimensions for your car’s proportions, and you have a working starting point. No need to build from scratch.
snappyHexMesh Configuration
The wind tunnel domain is a box. A common sizing: 5 car lengths upstream of the nose, 10 car lengths downstream of the tail, 3 widths either side, 3 heights above the roof. These aren’t magic — they just push the boundaries far enough that they don’t distort the flow around the car.
Set the surface refinement level for the car body at 4 or 5 in snappyHexMeshDict. Coarser runs faster and misses boundary layer detail. For a first pass, coarser is fine.
One thing that trips people up: the locationInMesh point must sit inside the fluid domain, not inside the car geometry. Put it a few car lengths upstream at mid-height and you won’t have to think about it again.
Boundary Conditions
For a 30 m/s freestream with k-epsilon turbulence:
- Inlet:
fixedValuevelocity (30 0 0 m/s), turbulence intensity around 0.05 - Outlet:
zeroGradientvelocity,fixedValuepressure at 0 - Car surface:
noSlipvelocity,zeroGradientpressure - Top and side walls:
slip, or symmetry if you prefer - Ground:
noSlipif you want to simulate ground effect,slipfor a simpler first run
Visualizing Results in ParaView
Run paraFoam from the case directory and it opens directly. Surface pressure shows where the car generates high- and low-pressure regions. Velocity streamlines from upstream into the wake make separation points obvious.
For quantitative output, add a forceCoeffs function object to controlDict. It integrates pressure and viscous forces across the car surface at each iteration. The absolute numbers won’t match a real wind tunnel, but relative comparisons between configurations — stock tail versus a spoiler, say — carry real meaning.
How Accurate Is This?
k-epsilon on a coarse mesh won’t capture separated flow accurately, and geometry simplifications compound the error. That’s fine. OpenFOAM at this level is a comparison and visualization tool. If two configurations produce meaningfully different drag or lift predictions, that’s a genuine signal worth paying attention to. If they look identical, don’t over-interpret that either.
The CFD Online forums cover most setup problems you’ll hit. The OpenFOAM Foundation documentation is also thorough — the User Guide section on meshing alone answers most snappyHexMesh questions that come up in the first few runs.
