checkMesh is the first thing you should run after generating any mesh in OpenFOAM. It reports non-orthogonality, skewness, aspect ratio, and a dozen other metrics — each of which can destabilize your solver if ignored. This guide walks through every section of the output and tells you exactly what to do when a check fails.
Run checkMesh from the case root directory after generating your mesh with blockMesh, snappyHexMesh, or an imported mesh:
# Serial case
checkMesh
# Save output to a log file
checkMesh > log.checkMesh 2>&1
# Parallel case (after decomposePar)
mpirun -np 8 checkMesh -parallel > log.checkMesh 2>&1
checkMesh reads the mesh from the constant/polyMesh directory. If you have multiple time directories with updated meshes (e.g., after mesh motion), specify the time with the -time flag:
checkMesh -time 0.5
The utility performs geometry checks first (cell volumes, face areas, non-orthogonality), then topology checks (connectivity, boundary patches), and finally mesh quality metrics. The report is structured into clearly labeled sections.
A typical checkMesh output has five sections. Understanding what each one reports prevents false alarms and missed problems.
The first block reports basic counts: number of cells, faces, internal faces, boundary patches, and points. This is a sanity check — verify the cell count matches your expected mesh resolution. A mesh with dramatically fewer cells than expected means blockMesh or snappyHexMesh didn't run correctly.
Mesh stats
points: 1234567
faces: 3456789
internal faces: 3200000
cells: 1100000
boundary patches: 6
After the geometry and topology checks, checkMesh prints a summary line:
Mesh OK.
-- or --
Failed 1 mesh checks.
Mesh OK means all checks passed. Failed N mesh checks lists which checks triggered. Note that warnings (non-fatal) and errors (fatal for the solver) are both reported here — you need to read the detail sections to distinguish them.
Non-orthogonality is the angle between the vector connecting two cell centres and the normal of the face between them. When this angle is large, the gradient correction across the face becomes inaccurate, reducing both stability and accuracy.
checkMesh reports the maximum and average non-orthogonality:
Mesh non-orthogonality Max: 67.3 average: 8.2
Acceptable thresholds by use case:
nNonOrthogonalCorrectors 1nNonOrthogonalCorrectors 2 or 3, switch Laplacian schemes to correctedFor non-orthogonality between 70° and 85°, add correctors to the pressure solver block:
SIMPLE
{
nNonOrthogonalCorrectors 2;
consistent yes;
}
// For transient (PISO block):
PISO
{
nCorrectors 2;
nNonOrthogonalCorrectors 2;
}
Switch the Laplacian and interpolation schemes to their corrected variants:
laplacianSchemes
{
default Gauss linear corrected;
}
snGradSchemes
{
default corrected;
}
The corrected scheme applies an explicit non-orthogonal correction. It increases accuracy at high non-orthogonality but adds computational cost. For non-orthogonality above 85°, even corrected may not stabilize the solver — rebuilding the mesh is the only robust solution.
Skewness measures how far the face interpolation point (the point where the line connecting two cell centres crosses the face) deviates from the geometric face centre. High skewness means interpolated values at the face are evaluated at the wrong location, introducing numerical error.
Max skewness = 3.72
Thresholds:
Unlike non-orthogonality, there is no numerical correction for high skewness — the only fix is improving the mesh. In snappyHexMesh cases, skewness spikes often occur at the boundary between the castellated hex core and the surface snapping layer. Reducing maxLocalCells or refining the surface feature extraction reduces these spikes.
Aspect ratio is the ratio of the longest to shortest dimension of a cell. checkMesh reports the maximum aspect ratio across all cells:
Maximum aspect ratio = 285.4
Context matters enormously here:
If checkMesh reports very high aspect ratios in regions you did not intend to have boundary layer cells, inspect the mesh in ParaView at those locations — snappyHexMesh sometimes produces distorted cells at concave geometry features.
checkMesh reports the minimum cell volume, maximum cell volume, and the ratio between adjacent cells:
Min volume = 1.23e-10 Max volume = 4.56e-05
Max cell openness = 2.3e-15
Max aspect ratio = 285.4
A negative cell volume is a fatal mesh error — the solver cannot run and will crash immediately. This happens when mesh generation produces inverted cells, often in snappyHexMesh when the castellated mesh is not properly constrained. Fix by:
nSmoothPatch iterations in snappyHexMesh if surface snapping over-distorts cellslocationInMesh point is inside the domain, not inside solid geometryA very large volume ratio between adjacent cells (greater than 100:1) causes interpolation errors at those interfaces. Smooth the mesh transition using grading in blockMesh or additional refinement levels in snappyHexMesh.
checkMesh validates each boundary patch for geometry consistency. A common warning is:
Boundary openness (-1.2e-16 2.3e-17 -4.5e-18) OK.
This is fine — the small values are floating-point noise. A genuine problem looks like:
***Boundary openness (0.023 -0.001 0.004) possible hole in boundary description.
This indicates a gap in the boundary definition — faces that belong to no patch, leaving the mesh open. This causes a mass imbalance and will result in divergence. Fix by checking that all surfaces in your CAD/STL geometry are watertight and that blockMesh definitions cover the entire domain boundary.
Both snappyHexMesh and checkMesh respect a meshQualityControls dictionary that sets the thresholds used during mesh generation. You can find this in system/meshQualityDict or embedded in system/snappyHexMeshDict:
meshQualityControls
{
maxNonOrtho 65;
maxBoundarySkewness 20;
maxInternalSkewness 4;
maxConcave 80;
minVol 1e-13;
minTetQuality -1e30;
minArea -1;
minTwist 0.02;
minDeterminant 0.001;
minFaceWeight 0.02;
minVolRatio 0.01;
minTriangleTwist -1;
nSmoothScale 4;
errorReduction 0.75;
}
snappyHexMesh will refuse to keep cells that violate these thresholds during the snap and layer addition phases. If you are getting unexpectedly low cell counts or missing layers, the mesh quality thresholds may be too strict for your geometry. Relax them incrementally, not all at once.
Most mesh quality issues in OpenFOAM originate from snappyHexMesh. The most effective interventions are:
nSurfaceLayers or reduce expansionRatio (try 1.15 instead of 1.3). More layers with gentler expansion produce lower non-orthogonality.castellatedMeshControls with features pointing to your extracted edge file (surfaceFeatureExtract).nSmoothPatch from 3 to 5, and increase tolerance from 2.0 to 4.0 in the snap phase.surfaceCheck constant/triSurface/geometry.stl and fix any inverted triangles in your CAD tool.Run checkMesh from the case root directory after mesh generation. For parallel cases, use checkMesh -parallel. Redirect output to a log file with checkMesh > log.checkMesh 2>&1 for easier review.
Max non-orthogonality below 70° is generally acceptable for RANS simulations. Above 70° you must add nNonOrthogonalCorrectors in fvSolution and switch to corrected Laplacian schemes. Values above 85° indicate a mesh that needs rebuilding.
Skewness measures how far the face interpolation point deviates from the face centre. Values below 4 are acceptable for most solvers. Above 4, accuracy degrades and divergence risk increases. Unlike non-orthogonality, there is no numerical corrector for skewness — the mesh itself must be improved.
For isotropic flow regions, aspect ratios above 100:1 degrade solver performance. In boundary layers where flow is predominantly streamwise, aspect ratios of 1000:1 or higher are normal and expected. The location of high-aspect-ratio cells matters more than the absolute value.
OpenFOAM will attempt to run even with checkMesh warnings, but negative cell volumes are fatal — the solver will crash immediately. Other warnings (high non-orthogonality, high skewness) degrade accuracy and stability but don't always prevent execution. You should fix them regardless.
Add nNonOrthogonalCorrectors 2 or 3 in the SIMPLE or PISO block in fvSolution. Also switch laplacianSchemes to Gauss linear corrected in fvSchemes. This compensates numerically but does not eliminate the underlying mesh quality problem — accuracy is still reduced compared to a good mesh.
Upload your case and CFDpilot reads your checkMesh output and flags the mesh issues most likely to cause divergence.
Diagnose my mesh →