OpenFOAM Mesh Generation — blockMesh and snappyHexMesh
#+CATEGORY: openfoam # :PROPERTIES: # :ID: uuid-openfoam-mesh-generation # :END:
OpenFOAM Mesh Generation :: blockMesh and snappyHexMesh Reference
This note documents OpenFOAM's native mesh generation tools: blockMesh (structured hexahedral blocks) and snappyHexMesh (unstructured hex/tet/poly hybrid mesh from STL geometry). It maps to Mesh Quality for quality metrics and Cell Types for structural considerations.
OpenFOAM mesh generation philosophy: blockMesh is for simple geometries where structured meshing is possible and desirable (rectangular domains, ducts, channels). snappyHexMesh is for complex geometries where an automated mesh generator is needed (external aerodynamics, internal flows with complex parts). The trade-off is that blockMesh produces higher-quality meshes, but snappyHexMesh handles arbitrary CAD.
**Table of Contents**
- blockMesh :: Structured hexahedral meshing
- snappyHexMesh :: Surface-conforming meshing pipeline
- Mesh Quality Control :: checkMesh, thresholds
- Mesh Adaptation :: refineMesh, dynamicRefineFvMesh
- cfMesh Comparison :: cfMesh vs snappyHexMesh vs blockMesh
- See Also
- References
blockMesh :: Structured Hexahedral Meshing
blockMesh is OpenFOAM's native structured mesh generator. It creates hexahedral meshes from user-defined blocks (O-grids, multi-block decompositions). It is the most basic and most powerful mesh generator in OpenFOAM: every face is controlled, every cell is known, and every mesh quantity can be verified analytically.
The mesh is defined in system/blockMeshDict:
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object blockMeshDict;
}
// Boundary definition
boundary
{
inlet
{
type patch;
faces
(
(0 0 0) (0 0 1) (0 1 1) (0 1 0)
);
}
outlet
{
type patch;
faces
(
(1 0 0) (1 1 0) (1 1 1) (1 0 1)
);
}
walls
{
type wall;
faces
(
(0 0 0) (0 1 0) (1 1 0) (1 0 0)
(0 0 1) (1 0 1) (1 1 1) (0 1 1)
);
}
}
// Blocks (single block shown)
blocks
(
hex (0 1 2 3 4 5 6 7) (100 50 50) simpleGrading (1 1 1)
);
// Edge definitions (for O-grid or curved boundaries)
edges
(
);
// Merge regions (for STL surfaces, if merging with snappyHexMesh)
mergeRegions
{
name mergeStl;
patches (inner outer);
}
| Parameter | Description | Typical value |
| ----------- | ------------- | --------------- |
| vertices | Mesh node coordinates (XYZ) | Defined per block corner |
| nCells | Cell count in each block direction | 100×50×50 (example) |
| simpleGrading | Cell sizing ratio per direction | (1 1 1) = uniform; (0.5 1 2) = graded |
| graded | Graduated cell spacing | (0.5 1 1) = cluster at inlet |
Graded meshes: simpleGrading = (a b c) applies grading in the x-direction, y-direction, z-direction respectively. A value of =a < 1/ clusters cells near the first face of the block; =a > 1/ clusters cells near the last face. For example, =simpleGrading (0.1 1 1)/ in a 100-cell x-direction block produces:
= \Delta x_i = \Delta x_0 \cdot r^{i-1} /
where =r = 0.1/ (the grading factor). The first cell is 10× smaller than the last cell (geometric progression). The ratio between adjacent cells is:
= \frac{\Delta x_{i+1}}{\Delta x_i} = r /
For =r = 0.1/, the cell size decreases by 10× per cell going from last to first face. This is critical for boundary layer resolution: if you need y+ ~ 1 in the first cell, =h_1 = y^+ \nu / u_*, you use grading in the wall-normal direction.
blockMesh is ideal for:
. Canonical test cases (channel flow, pipe flow, cavity flow) . Verification cases where the mesh is known analytically . Simple domains (rectangular boxes, multi-block O-grids around cylinders) . LES verification where cell alignment with flow is critical (structured hex provides lowest numerical anisotropy)
blockMesh is unsuitable for:
. Complex geometries (external aerodynamics with CAD surfaces) . Detailed internal flows with multiple components . Anything requiring STL import
For complex geometries, snappyHexMesh is the answer — though it can be combined with blockMesh as the background hexahedral mesh.
snappyHexMesh :: Surface-Conforming Meshing Pipeline
snappyHexMesh is OpenFOAM's surface-conforming mesh generator. It starts with a background hexahedral mesh (from blockMesh or a uniform background), then:
1. Cast — "skeleton rays" from background cell centres to determine inside/outside based on STL surface 2. Snap — Move surface-intersecting cell faces to match the STL surface (conformal mesh) 3. Add layers — Add prism layers on specified patches for boundary layer resolution (optional)
The configuration is in system/snappyHexMeshDict:
/* snappyHexMeshDict */
castPoints -1; // cast rays n times to improve inside/outside detection
castShadows off; // cast occlusion shadows for refining in wake of obstructions
// Step 1: Refinement
refinement
{
// Background refinement (coarse mesh)
background min 2 max 4 level 3; // cells = base / 2^level
// Surface-based refinement (refine near STL surface)
surfaceRegions
{
wall min 3 max 5 level 4; // refinement near boundary
}
// Field-based refinement (refine where field exceeds threshold)
fields
(
"velocity:3" // refine where |U| > 3 m/s
)
}
// Step 2: Feature refinement (refine at sharp edges)
refinementRegions
{
cylinder
{
faces (<point1> <point2>); // bounding box
level (6 6 6); // refinement level
}
}
// Step 3: Surface snap
snap
{
nSmoothSnap 3; // smoothing iterations
nSmoother 5; // face smoothing iterations
nUnfavourite 3; // eliminate unfavourable faces
nFaceDrop 2; // drop faces if mesh quality is poor
tolerance 1.0; // snap tolerance
}
// Step 4: Layer addition
addLayers
{
layers
{
wall (6 1 1 0.2); // [nLayers, growthRate, ratio, thickness]
}
expansionRatio 1.2; // growth rate between layers
finalLayerThickness 0.001; // thickness of last layer
thickness 0.01; // total boundary layer height
nDimSmooth 3; // smoothing iterations in nD
nSmooth 10; // smoothing iterations
nRelaxIter 5; // relaxation iterations (smoothing)
errorControl on; // stop if mesh quality drops below threshold
maxFirstLayer yes; // enforce maximum first-layer height
absoluteFirstLayer no; // firstLayer absolute (not relative)
nSmoothTerrain 10; // terrain smoothing (for surface normals)
}
Key snappyHexMesh concepts:
. CAST (Step 1) — The algorithm casts rays from each background cell centre to the STL surface. Cells whose centres fall inside the geometry (as determined by ray-casting intersection parity) are marked for removal/cutting. The quality of the cast is improved by =castPoints/ and =castShadows/. A value of =castPoints = -1/ means infinite iterations until convergence. =castShadows/ refines cells in the "shadow" of surface protrusions (useful for wake refinement).
. Snap (Step 2) — Face nodes on the STL surface are moved to match the STL geometry. The smoothing algorithm (Laplacian smoothing) preserves mesh quality during snapping by spreading the displacement from snapped nodes to neighbouring nodes. The tolerance parameter controls how far a face node can move — too small, and the surface isn't conformal; too large, and cell quality degrades (skewness, aspect ratio violations).
. Add layers (Step 3) — After snapping, prism layers are added to wall patches. The =addLayers/ control has the same format as cfMesh's boundary layer specifications. However, snappyHexMesh has more parameters for quality control and recovery (errorControl, maxFirstLayer, absoluteFirstLayer). It can also un-layer cells (reverse the layer addition) if the mesh quality drops below a threshold.
Mesh Quality Control :: checkMesh and Thresholds
After mesh generation, checkMesh evaluates the mesh quality:
[#BEGIN_SRC bash checkMesh -allGeometry -allTopology
#+END_SRC
| Quality Metric | Acceptable | Good | Excellent |
| ---------------- | ------------ | ------ | ----------- |
| Skewness (0–1) | < 0.85 | < 0.7 | < 0.5 |
| Orthogonality (0–1) | > 0.2 | > 0.5 | > 0.7 |
| Max non-orthogonality (°) | < 70 | < 50 | < 30 |
| Face concavity | < 5 | < 2 | < 1 |
| Face determinant | > 0.001 | > 0.1 | > 0.5 |
| Cell determinant (high-accuracy) | > 0.1 | > 0.3 | > 0.5 |
| Cell volume | Positive | Uniform (no > 10× ratio) | Uniform (no > 2× ratio) |
| Face area | Positive | Uniform (no > 10× ratio) | Uniform (no > 5× ratio) |
The most important quality metrics for simulation accuracy are:
. Skewness — measures how much a cell deviates from a symmetric shape. High skewness introduces interpolation error and degrades gradient accuracy. The relationship is: if a cell is highly skewed, the line between cell centres does not pass through the face centre, and the face interpolation =\phi_f = (\phi_P + \phi_N) / 2/ introduces systematic error.
. Orthogonality — measures the angle between the vector connecting cell centres and the face normal vector:
= \text{orthogonality} = \frac{|\vec{H} \cdot \vec{S}|}{|\vec{H}| \cdot |\vec{S}|}
For orthogonal meshes (H parallel to S), orthogonality = 1. For highly non-orthogonal meshes (H nearly perpendicular to S), orthogonality → 0. The non-orthogonal correction in the laplacian scheme (see Numerical Schemes) accounts for this, but the correction is more expensive and less accurate as orthogonality degrades.
. Cell determinant — measures the quality of the cell's shape by evaluating the Jacobian determinant of the mapping between reference coordinates and physical coordinates. A negative determinant means the cell is inverted (computationally invalid). A determinant near zero means the cell is extremely distorted.
For CFD accuracy, all interior cells should have skewness < 0.7, orthogonality > 0.5, and determinant > 0.1. Boundary cells can tolerate slightly higher skewness because they are near the surface where mesh quality is hardest to control.
Mesh Adaptation :: refineMesh and dynamicRefineFvMesh
OpenFOAM supports mesh refinement and adaptation during simulation (h-refinement):
| Tool | Purpose | Dynamic |
| ------ | --------- | --------- |
| refineMesh | Static refinement (post-processing) | No |
| refineToRegion | Refine specified regions | No |
| dynamicRefineFvMesh | Adaptive mesh during simulation | Yes |
| dynamicFvMesh | General dynamic mesh (moving) | Yes |
dynamicRefineFvMesh is the tool for adaptive mesh refinement (AMR). It refines and coarsens the mesh during simulation based on user-defined criteria:
/* dynamicRefineFvMesh */
refineMesh
{
minRefinement (1 1 1); // minimum refinement in each direction
maxRefinement (6 6 6); // maximum refinement per cell
nBufferLayers 1; // buffer layers around refined region
level 4; // refinement level for field-based refinement
// Refine criteria
fields
(
"velocity:1" // refine where U > 1 m/s
);
// Max cells
maxCells 5e6; // cap at 5 million cells
}
AMR is particularly useful for LES/DNS simulations where the mesh must resolve the smallest scales in regions of high turbulence. The refinement criteria can be based on any field: vorticity magnitude, strain rate, turbulence kinetic energy gradients, or any user-defined function.
OpenFOAM's AMR is implemented via =polyTopoChange/, which modifies the mesh topology (adds/removes cells, changes connectivity) at each adaptation step. The field data is interpolated from the old mesh to the new mesh. The interpolation preserves conservation for primary flow variables (U, p, rho).
cfMesh Comparison :: cfMesh vs snappyHexMesh vs blockMesh
See also cfMesh Workflow and ANSYS Meshing & Post-Processing.
| Feature | blockMesh | snappyHexMesh | cfMesh |
| --------- | ----------- | --------------- | -------- |
| Mesh type | Structured hex | Hex/tet/poly hybrid | Hex/tet hybrid |
| Geometry | Boxes, O-grids | STL conformal | STL cut |
| Mesh quality | Highest | Moderate (depends on settings) | Lower (staircase surface) |
| Automation | Manual (blocks) | High (STL-based) | High (meshDict) |
| Boundary layers | None (manual grading) | AddLayers (6+ layers) | Prism layers |
| AMR support | No (static) | No (static) | No (static) |
| Best use case | Verification, canonical cases | Production simulations | Rapid mesh generation |
| Learning curve | Low (but skill required) | High | Low |
snappyHexMesh is the standard choice for production simulations because it offers the best trade-off between quality and automation. blockMesh is the choice for verification and when mesh quality is paramount (LES, DNS). cfMesh is the choice when automation is prioritised over quality (rapid prototyping, initial design exploration).
See Also :: Related Notes
. Mesh Quality — quantifying mesh quality metrics . Cell Types — hex, tet, poly, hybrid mesh quality implications . cfMesh Workflow — cartesian meshing comparison . OpenFOAM Case Setup — mesh files in constant/polyMesh . OpenFOAM Solver Selection — solvers that require specific mesh quality . ANSYS Meshing & Post-Processing — Fluent Meshing comparison
References
. OpenFOAM User Guide. ESI OpenCFD. (blockMesh and snappyHexMesh documentation.) . OpenFOAM V2012 Programming Guide. ESI OpenCFD. (polyTopoChange for dynamic mesh topology.) . Versteeg, H.K. & Malalasekera, W. (2007). An Introduction to CFD. Chapter 4 (Mesh generation). . Jänicke, C., & Hege, H.-C. (2017). "cfMesh: An open-source mesh generator for CFD." cfMesh 2017 Proceedings.