Skip to content
Draft. This manual is new and still being checked against the software as it is verified. Some pages will change. If something here does not match what you see, the software is right — tell us and we will fix the page.

Lid-driven cavity, Re = 100

State: written up. The comparison table below is complete and may be cited.

Case: Lid-driven cavity (validation) Reference: Ghia U., Ghia K.N., Shin C.T., “High-Re solutions for incompressible flow using the Navier–Stokes equations and a multigrid method”, Journal of Computational Physics 48 (1982) 387–411, Table I.

Last run: 2026-08-07, against the tree at that date, bundled OpenFOAM v2606.

The standard verification problem for an incompressible code: a square box of still fluid with the top wall dragged sideways. It has no analytic solution, but Ghia et al. solved it on a 129×129 grid with a multigrid method and tabulated the velocity along the centrelines, and those tables have been the check on incompressible solvers ever since.


Domain 0.1 m square, one cell thick, frontAndBack empty
Mesh 20 × 20 cells, uniform (400 cells)
Lid 1 m/s, movingWallVelocity; the other three walls no-slip
Fluid ρ = 1 kg/m³, ν = 10⁻³ m²/s → Re = UL/ν = 100
Solver icoFoam — laminar, transient, PISO
Run to t = 40 s on Δt = 0.002 s, Courant 0.4

Forty seconds is four viscous diffusion times (L²/ν = 10 s), which is what the cavity settles on. It is steady well before the end: between t = 30 s and t = 40 s the largest change anywhere in the field is 4 × 10⁻⁸ m/s.


u along the vertical centreline, normalised by the lid speed:

y/L Ghia et al. SHD Sim CFD difference
1.0000 +1.00000 +1.00000 +0.00000
0.9766 +0.84123 +0.83133 −0.00990
0.9688 +0.78871 +0.78117 −0.00754
0.9609 +0.73722 +0.73196 −0.00526
0.9531 +0.68717 +0.68337 −0.00380
0.8516 +0.23151 +0.23338 +0.00187
0.7344 +0.00332 +0.00293 −0.00039
0.6172 −0.13641 −0.13429 +0.00212
0.5000 −0.20581 −0.19896 +0.00685
0.4531 −0.21090 −0.20324 +0.00766
0.2813 −0.15662 −0.15062 +0.00600
0.1719 −0.10150 −0.09787 +0.00363
0.1016 −0.06434 −0.06215 +0.00219
0.0703 −0.04775 −0.04530 +0.00245
0.0625 −0.04192 −0.04064 +0.00128
0.0547 −0.03717 −0.03599 +0.00118
0.0000 +0.00000 +0.00000 +0.00000

RMS difference 0.0047. Worst point 0.0099 — that is 0.5% and 1.0% of the lid speed.

The zero crossing, which is where the primary vortex sits and the most demanding thing on the table to get right, is at y/L = 0.734 against Ghia’s 0.7344.


Mesh, not physics. This is 400 cells against Ghia’s 16 641, and the two largest differences are both in the top 5% of the box, where the lid drags a thin shear layer that twenty cells cannot resolve. The interior agrees to about half a percent. Refining the mesh in the app closes the gap; the coarse mesh is used here deliberately, because a benchmark that only agrees when it is expensive is not much of a reassurance.


Building this benchmark was the first time the product had ever been asked for a published answer, and it immediately found two faults that had been in the software the whole time:

  • PISO cases could not run at all. fvSolution named its transient block PIMPLE whatever the algorithm was, with nOuterCorrectors 1 standing in for PISO. pimpleFoam accepts that; pisoFoam and icoFoam do not — they build a pisoControl, which wants a PISO sub-dictionary and stops without one. Selecting the PISO algorithm selects pisoFoam, so every PISO case the app had ever written stopped at start-up.
  • Closed domains could not run at all. With no pressure outlet the pressure level is undetermined and OpenFOAM asks for pRefCell and pRefValue. The app’s own validation rule said these “will be written to pin the level”. Nothing wrote them — the string appeared nowhere in the product. Any sealed case — a cavity, a tank, a stirred vessel — stopped with “Unable to set reference cell for field p”. This is almost certainly why the buoyant cavity example had never been solved end to end.

Both are fixed, and the second is the more embarrassing: the software described a thing it did not do.

This section is kept because it is the evidence that the process works. A benchmark that only ever confirms what was already believed is not being used for anything.


The cavity checks four things: incompressible laminar flow, the pressure–velocity coupling, wall conditions, and 2-D handling. It says nothing about the rest of the product, and in particular nothing about:

  • Turbulence. There is no turbulence model in the case at all — icoFoam has none. Every RANS and LES model in the product is untouched by this page.
  • Wall functions and near-wall treatment. No wall model is exercised; the walls are resolved no-slip on a uniform mesh.
  • Separation and reattachment. The recirculation here is fixed by the geometry — it is driven into a corner. Nothing asks the solver to predict where a shear layer detaches or lands.
  • Unsteady flow. The run is transient only as a route to a steady answer. No periodic or genuinely unsteady behaviour is checked.
  • Inlets and outlets. The domain is sealed. Inlet profiles, outlet conditions and far-field boundaries are all unexercised.
  • Meshing. This is a uniform block, not a snapped mesh. snappyHexMesh, surface refinement and boundary layers are not involved.
  • Compressibility, heat, buoyancy, multiphase, particles, reacting flow — none of it. Those solvers share the case machinery, not the answer.
  • Three dimensions. The case is a plane problem solved one cell thick.

Everything in that list is why the benchmark list exists.


Nothing here is set up by hand or outside the product.

  1. Worked example → Lid-driven cavity (validation)
  2. Generate mesh
  3. Run

The example seeds the domain, the two-dimensional setting, the icoFoam solver, the fluid properties and the run control listed above. If any of those values differ from the set-up table, the table is what was actually run and the example has since changed — say so rather than editing the numbers.


Format for new benchmarks: _TEMPLATE.md.