A two-dimensional cell-centred finite-volume CFD solver written from scratch in C++17, carried from analytical verification and a lid-driven cavity benchmark through to wall-resolved k-omega SST simulations of a NACA 0012 at a chord Reynolds number of 6×10⁶.
Nothing here is delegated to a CFD package. Geometry, mesh generation, the finite-volume discretisation, the SIMPLE pressure-velocity coupling, the non-orthogonal correction and the turbulence model are all implemented in this repository. There is no external numerical library either: the linear systems are solved by a Gauss-Seidel sweep with over-relaxation written for this project. The only third-party code involved is NumPy and Matplotlib, used for plotting after the fact.
Velocity magnitude around the NACA 0012 at 10° incidence and Re = 6×10⁶, from the k-omega SST solver with limited second-order convection.
| Check | Result |
|---|---|
| Laplace on an annulus, against the analytical solution | 2nd order, observed 1.98 → 2.00 |
| Convection-diffusion, central differencing | 2nd order, observed 2.02 → 2.00 |
| Convection-diffusion, first-order upwind | 1st order, observed 0.73 → 0.95 |
| Lid-driven cavity at Re = 100, against Ghia et al. (1982) | centreline profiles matched |
| Lift at zero incidence, where the exact answer is zero | Cl = 2.3×10⁻⁷ |
| Lift at 10° against the NASA three-code SST mean of 1.079 | Cl = 1.119, 3.6 % high |
| Near-wall resolution in the final solution | mean y⁺ = 1.07, no wall functions |
Reference data comes from Ghia, Ghia and Shin (1982) for the cavity, and from the NASA Turbulence Modeling Resource for the turbulent aerofoil.
Every program is a self-contained translation unit with its own main(). They
communicate through CSV files on disk rather than through a shared library,
which is what allows any stage to be re-run without rebuilding the ones before
it. The layout follows the order the project was actually built in.
src/
├── verification/ analytical cases, solved before anything was trusted
│ ├── laplace_annulus_verification.cpp Laplace on an annulus
│ └── convection_diffusion_verification.cpp central vs first-order upwind
├── cavity/ lid-driven cavity, built up in stages
│ ├── lid_driven_cavity_stage2_u_predictor.cpp momentum predictor alone
│ └── lid_driven_cavity_final.cpp full SIMPLE loop, Re = 100
├── mesh/ geometry and structured O-grid generation
│ ├── naca_geometry.cpp NACA 4-digit surface coordinates
│ ├── naca_fvm_geometry.cpp cell metrics, areas, normals
│ ├── laplace_naca_v1.cpp first O-grid, elliptic smoothing
│ ├── generate_highRe_mesh.cpp rebuilt O-grid for y⁺ ≈ 1
│ └── generate_grid_convergence_meshes.cpp coarse, medium and fine meshes
└── solver/ the aerofoil solver
├── naca_flow_setup.cpp fields, boundary conditions, initialisation
├── naca_momentum_predictor.cpp momentum predictor on the aerofoil mesh
├── naca_simple_orthogonal.cpp SIMPLE, orthogonal fluxes only
├── naca_simple_nonorth.cpp with the non-orthogonal correction
├── naca_sst.cpp k-omega SST, first-order convection
├── naca_sst_alpha0.cpp the same at 0°, as a symmetry check
└── naca_sst_second_order.cpp limited second-order convection, final
python/ holds the post-processing and the convergence analysis, data/ the
small reference results the figures are drawn from, and scripts/ the
PowerShell driver used for the grid-convergence sweep. The multi-megabyte field
files each run produces are not tracked.
Requires a C++17 compiler, CMake 3.20 or newer, and Ninja. On Windows this was built with MinGW-w64 UCRT64 from MSYS2.
cmake -S . -B build -G Ninja
cmake --build buildThat produces one executable per program in build\. On MinGW they are linked
statically, so they carry their own runtime and will start on a machine with no
MSYS2 installation and nothing added to PATH.
Each program writes its CSV output to the current working directory, so run
them from output\ to keep results out of the source tree. The two analytical
verification cases take about a minute each and need no input:
cd output
..\build\laplace_annulus_verification.exe
..\build\convection_diffusion_verification.exeThe aerofoil cases read the mesh written by the mesh generator, so those run in order:
..\build\generate_highRe_mesh.exe
..\build\naca_sst_second_order.exeThe turbulent aerofoil runs take hours. The cavity and verification cases are the quick way to see the numerics working.
python -m pip install numpy scipy pandas matplotlib
python ..\python\plot_naca_sst.py