A serial C++17 solver for the two-dimensional incompressible lid-driven cavity benchmark.
The production solver uses a staggered Marker-and-Cell arrangement, a pseudo-transient projection method, compatible pressure-gradient and divergence operators, and convergence-aware termination. The repository also contains manufactured Poisson verification, discrete-operator tests, sanitizer builds, Ghia centerline comparisons, and configurable parameter studies.
The current Phase 2 regression set has been exercised with:
- the canonical
N=32,Re=100, upwind, RBSOR case; - all six
N=32combinations atRe=100,400, and1000with upwind and central convection using RBSOR; - the
N=16,32, and64,Re=100, central, RBSOR grid sequence; - RBGS/RBSOR manufactured Poisson tests;
- the compatibility test between the selected divergence, gradient, and Laplacian operators;
- GCC and Clang builds in Debug and Release configurations;
- AddressSanitizer and UndefinedBehaviorSanitizer checks.
The canonical strict case converges automatically rather than stopping at a configured iteration limit.
The solver advances the nondimensional incompressible Navier–Stokes equations using:
- a staggered MAC grid;
- an explicit pseudo-time momentum predictor;
- upwind or central convection differencing;
- a pressure-correction Poisson equation;
- RBGS or RBSOR pressure iteration;
- velocity correction using pressure gradients located consistently with the staggered velocity components;
- convergence checks based on velocity updates, local divergence, global mass balance, and pressure convergence.
Velocity components are stored on cell faces and pressure is stored at cell centers. Cell-centered velocity values are reconstructed for CSV output and post-processing.
A production case is reported as converged only when all of the following remain satisfied for the configured number of consecutive iterations:
- dimensionless velocity-update
Linfresidual; - dimensionless divergence
Linfresidual; - dimensionless divergence
L2residual; - global boundary mass imbalance;
- successful pressure-Poisson convergence.
Possible terminal states include:
convergedmax_iterationspressure_not_convergedstagnateddivergednon_finite
Use --strict when a script or CI job must fail if any requested case does not converge.
On Linux, WSL, or a Linux HPC node:
bash scripts/run_single.shThis builds the solver and runs the canonical strict case:
N = 32
Re = 100
scheme = upwind
pressure solver = RBSOR
A successful run ends with status=converged and writes CSV files to results/data/.
bash scripts/run_smoke_test.sh # compilation and output check only
bash scripts/run_single.sh # canonical converged regression
bash scripts/run_quick.sh # four fast Re=100 cases
bash scripts/run_medium.sh # six N=32 cases at Re=100/400/1000
bash scripts/run_grid.sh # N=16/32/64 grid sequence at Re=100
bash scripts/run_re1000.sh # converged N=32, Re=1000 central case
bash scripts/run_full.sh # complete 36-case configurationThe full mode includes RBGS and grids up to N=128; it is intended for a workstation or HPC node.
bash scripts/build.sh
bin/lid_cavity \
--single \
--N 32 \
--Re 100 \
--scheme upwind \
--pressure RBSOR \
--strictImportant numerical options include:
--maxIter
--poisson-maxIter
--tol-velocity
--tol-divergence
--tol-divergence-l2
--poisson-tol
--alpha-u
--alpha-p
--cfl
--dt-max
--min-iterations
--consecutive-passes
Run bin/lid_cavity --help for the complete interface.
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
ctest --test-dir build --output-on-failureThe CTest suite includes:
- discrete operator verification;
- manufactured Poisson verification and grid refinement;
- convergence-state logic;
- the canonical production-solver regression.
For sanitizer checks:
cmake -S . -B build/sanitized \
-DCMAKE_BUILD_TYPE=Debug \
-DLIDCAVITY_ENABLE_SANITIZERS=ON
cmake --build build/sanitized --parallel
ctest --test-dir build/sanitized --output-on-failureEach case writes:
results/data/study_summary_<mode>.csv
results/data/case_<id>_..._history.csv
results/data/case_<id>_..._fields.csv
The summary separates:
- execution status;
- iterative convergence;
- pressure convergence;
- divergence metrics;
- runtime;
- Ghia benchmark agreement.
The history file stores iteration-by-iteration convergence information. The field file contains cell-center coordinates, velocity, pressure, speed, and vorticity.
For Re=100, 400, and 1000, the solver compares:
- horizontal velocity
u(y)on the vertical centerline; - vertical velocity
v(x)on the horizontal centerline.
The code reports L2 and Linf errors. These are reference-benchmark comparisons, not experimental validation.
src/lid_cavity.cpp production staggered-grid solver
include/lidcavity/ reusable verification interfaces
src/verification/ operator, Poisson, and convergence components
tests/ CTest verification programs
scripts/ build and run helpers
postprocess/ Python plotting scripts
docs/ method and verification notes
results/data/ generated CSV output
.github/workflows/ smoke and numerical-verification CI
This is an educational CFD and numerical-verification project, not a production CFD package.
Current limitations include:
- serial CPU execution only;
- explicit pseudo-time momentum advancement;
- no multigrid pressure solver;
- no formal experimental validation;
- the exhaustive 36-case study can be computationally expensive, especially with RBGS and
N=128.
Parallel C++, MPI, OpenMP, CUDA, MATLAB, and Python comparisons belong to the separate solver-comparison project and are intentionally not developed in this repository.
Ghia, U., Ghia, K. N., & Shin, C. T. (1982). High-Re solutions for incompressible flow using the Navier–Stokes equations and a multigrid method. Journal of Computational Physics, 48(3), 387–411.
Ahmed Kandil — Portfolio · LinkedIn · ORCID
Released under the MIT License.