OpenFOAM 14 Part 2: Building a Mesh with blockMeshDict

by giux CFD and OpenFOAM 24 min read

Part 2 of 8 of the case-construction series in the Learning OpenFOAM 14 path: from geometry to a verified volume mesh.

The task. Construct a three-dimensional channel from eight vertices, choose its cell distribution, assign every boundary face, and verify the generated mesh.
The result. A complete system/blockMeshDict, a minimal mesh-only case, and a method for reading the corresponding official documentation.

Schematic hexahedral structured mesh of the rectangular duct built with blockMesh
Schematic structured mesh. The illustration is coarsened and not to scale.
Video lesson on Part 2 (in English), generated with Gemini Notebook from the material of this part.

How to use this part

Part 1 introduced the language and the conceptual trainingChannel directory. This part turns that name into a concrete mesh. It belongs to the dictionary-construction series, not to the initial practical cases.

Keep a terminal and this article side by side. Read the geometry and ordering sections first; then type the complete files in sections 10 and 11. The answer notes are in section 20, after the exercises.

Reading routeSectionsWhat you will do
Specify and describe1–4Set dimensions, label vertices and define a right-handed block.
Distribute cells5–7Choose resolution and understand one-way or symmetric grading.
Name the boundary8–9Separate patch identity, mesh type and face ordering.
Build and inspect10–15Create the two files, generate the mesh and compare predictions.
Work independently16–20Modify, diagnose and construct a second channel.
Use the documentation21 and referencesFind syntax, examples and primary references.

Main outcome
You should be able to explain how every major section of blockMeshDict changes the geometry, topology, cell distribution or patch assignment. A working file without that explanation is not the endpoint.

Scope and prerequisites

Use a Bash shell with Foundation OpenFOAM 14 loaded, and your own writable case directory. You need basic editing and navigation, plus the dictionary syntax from Part 1. No C++ development, CAD model, turbulence model or flow solver is required here.

Optional recall boxes
Recall boxes contain background or derivations. They can be skipped without interrupting the main practical route.

Documentation: Part 1, §1.1 and §B.1. Public references [R1]–[R10] are listed at the end of the article.

1. Specify the channel before typing

The example is a three-dimensional rectangular duct. Its intended flow direction is +x. All four long faces are walls; the x-normal end faces are the inlet and outlet. These are teaching choices, not reactor dimensions or experimentally validated settings.

QuantityInput valueMeaning
Length L100 mmx: from inlet to outlet
Height H10 mmy: between the lower and upper walls
Depth W5 mmz: between the two side walls
Cells40 × 10 × 5Local x, y and z directions
Grading1 × 1 × 1Initially uniform along each direction
Patch namesinlet / outlet / wallsThe names carried into later field files
Reference hexahedral block with the eight vertices labelled 0 to 7 and x, y, z axes
Figure 1. The reference block. Depth and height are enlarged for readability; the numerical coordinates determine the actual proportions.

Write these predictions first
The bounding box in the default SI system is (0 0 0) to (0.1 0.01 0.005) m. There are 2,000 cells. The volume is 5 × 10⁻⁶ m³. You will use these independent predictions to catch unit and resolution errors.

Documentation: [R1], §§5.4.2–5.4.5. Numerical values and geometry in this part are original teaching examples.

2. The file is a recipe, not the mesh

blockMesh reads the block description, creates cells and connectivity, and writes a mesh into constant/polyMesh/. The eight block vertices are control points for the construction; they are not the full list of generated mesh points.

system/blockMeshDict
        |
        |  blockMesh
        v
constant/polyMesh/
    points   faces   owner   neighbour   boundary
EntryHow to read itRole in this lesson
FoamFileA sub-dictionary in bracesIdentifies a dictionary object named blockMeshDict.
unitsA length-unit entryInterprets input coordinates as millimetres.
verticesA parenthesised listSupplies the eight corner coordinates.
blocksA parenthesised listDefines connectivity, cell counts and grading.
boundaryA list of named sub-dictionariesAssigns the six exterior block faces to patches.

Read punctuation as structure

A vector such as (100 10 5) is a list of components. A vertices (...); entry ends with a semicolon after the closing parenthesis. Each patch body uses braces. The boundary entry itself is a list, not a single brace-enclosed sub-dictionary.

Omitted on purpose
Straight edges need no edges entry. This one-block case also needs no mergePatchPairs. No exterior face will be left to an implicit default patch. Add a feature only when the geometry requires it.

Documentation: [R1], §§5.4.1, 5.4.4, 5.4.7–5.4.8; [R2]; dictionary grammar: [R4].

3. Vertices: labels are list positions

The first entry in vertices has label 0, the second label 1, and so on. Comments are reminders for the reader; the comments do not assign the labels. Reordering the list changes the meaning of all references to it.

units [mm];

vertices
(
    (  0   0  0)   // 0
    (100   0  0)   // 1
    (100  10  0)   // 2
    (  0  10  0)   // 3
    (  0   0  5)   // 4
    (100   0  5)   // 5
    (100  10  5)   // 6
    (  0  10  5)   // 7
);
The two planes z = 0 and z = 5 mm with vertices 0-3 and 4-7 in the same x-y orientation
Figure 2. The two z-planes shown separately. Pairs 0-4, 1-5, 2-6 and 3-7 match across the depth. Both are viewed in the same x-y orientation, not from opposite sides of the duct.

A quick consistency check

Vertices 0-3 lie at z = 0; vertices 4-7 lie at z = 5 mm. Each pair across the depth differs only in z. The x coordinates take only 0 or 100; the y coordinates take only 0 or 10.

Units: convert once
With units [mm];, enter 100 for 100 mm, not 0.1. The generated mesh uses the base length unit, metre in the default SI setup. Do not also add a millimetre-to-metre scale factor to this example.

Documentation: [R1], §§5.4.2–5.4.3; [R4], units and list syntax.

4. The hex order defines local directions

blocks
(
    hex (0 1 2 3 4 5 6 7) (40 10 5)
    simpleGrading (1 1 1)
);

hex describes a hexahedral block. The first four labels trace one quadrilateral; the next four are its corresponding vertices across the third direction. In this particular rectangular block, the local directions coincide with global x, y and z.

Local directionHow to identify it hereControls
1: +x0 → 140 cells; first grading value
2: +y1 → 2 (parallel to 0 → 3)10 cells; second grading value
3: +z0 → 45 cells; third grading value

Why the order cannot be arbitrary

The block must be right-handed. For this rectangular example, take e₁ = r₁ − r₀, e₂ = r₃ − r₀, and e₃ = r₄ − r₀. Their scalar triple product is positive. An arbitrary swap of labels can invert or twist the block instead of merely renaming its corners.

Optional recall / right-handedness
For this parallelepiped, (e₁ × e₂) · e₃ = LHW = 5,000 mm³ > 0. The sign checks orientation; the value is its volume. This single corner calculation is not a general quality test for a curved or warped hexahedron.

Separate a block from its cells

One hex entry does not mean one computational cell. It describes the region that will be subdivided into 40 × 10 × 5 = 2,000 cells. Rotating a block can change the relation between local cell-count directions and the global axes.

Documentation: [R1], §5.4.5; [R8], built-in block-ordering description. Triple-product calculation: derived for this example.

5. Resolution is independent of size

Coordinates set the physical domain. Cell counts set how finely that domain is divided. With uniform grading, the reference cell sizes are obtained directly from the three lengths.

DirectionCalculationCell size
x100 mm / 402.5 mm
y10 mm / 101.0 mm
z5 mm / 51.0 mm

Predict before you change the file

ChangeCell countWhat stays the same
Baseline: (40 10 5)2,000Reference domain and patches
Only x: (80 10 5)4,000Domain size; y and z cell widths
All directions: (80 20 10)16,000Domain size and patch locations
Double L; keep (40 10 5)2,000Topology; x cells become twice as long

Doubling the counts in three directions multiplies the number of cells by eight. That arithmetic alone does not specify the increase in simulation time, which also depends on the solver, time step and convergence behaviour.

Optional recall / cells are control volumes
A finite-volume method balances quantities over cells and exchanges fluxes through their faces. Refinement changes the spatial approximation; it does not add new physical dimensions to the problem. A mesh that passes geometric checks can still be too coarse for the quantity of interest.

Do not turn a 3D duct into a 2D model accidentally

The baseline has five cells through its depth and wall patches on both z-faces. A one-cell-thick mesh is not automatically a valid two-dimensional model. An empty direction requires compatible geometry and matching field conditions; it is not used in this lesson.

Documentation: [R1], §5.4.5; two-dimensional constraints: [R3]. All counts in the tables are analytical predictions.

6. Grading: end cell divided by start cell

For a direction with N cells, simpleGrading uses the overall expansion ratio E = Δlast/Δfirst. It is not the ratio between neighbouring cells. Here the y-direction runs from the lower wall at y = 0 to the upper wall at y = H.

simpleGrading (1 4 1)
Ten cells across the same length with expansion ratio E = 1, 4 and 0.25
Figure 3. Ten cells across the same length. E > 1 places the smaller cells at the start; E < 1 places them at the end. The plots are calculated distributions, not OpenFOAM output.

For H = 10 mm, N = 10 and E = 4, the first cell is about 0.4542 mm wide and the last is about 1.8170 mm. The number of cells and the overall height remain unchanged.

Optional recall / geometric progression
With N > 1, neighbouring widths have ratio q = E1/(N−1). For q ≠ 1, Δfirst = H(q − 1)/(qN − 1). For E = 1, use Δ = H/N. In this example q ≈ 1.1665, not 4.

A useful prediction

Changing (1 1 1) to (1 4 1) refines near y = 0 and coarsens near y = H. It does not refine both walls. Changing it to (1 0.25 1) reverses that distribution.

Documentation: [R1], §5.4.5. Cell-width calculations and Figure 3 follow the geometric progression above.

7. Optional: refine towards both walls

A single ratio gives one-way grading. To keep a single block but refine towards both y-walls, split the y-direction into two grading sections. This optional example uses 20 cells in y instead of the baseline 10.

blocks
(
    hex (0 1 2 3 4 5 6 7) (40 20 5)
    simpleGrading
    (
        1
        (
            (0.5 0.5 4)
            (0.5 0.5 0.25)
        )
        1
    )
);

Each inner triple means (fraction of length, fraction of cells, expansion ratio). The lower half occupies 50% of the height and gets 50% of the 20 y-cells. The upper half does the same, with the reciprocal expansion.

Two-section grading with fine cells towards both walls and coarse cells at the centre
Figure 4. Symmetric two-section grading: 10 cells with E = 4 and 10 cells with E = 0.25. Both centre-adjacent cells have the same width because the two sections are equal and their ratios are reciprocal.

What to verify

The new mesh contains 4,000 cells and has the same bounding box. Cell widths near either y-wall are about 0.2271 mm; the two centre-adjacent widths are about 0.9085 mm. These values describe this example only.

Keep the main route simple
Use the uniform baseline in section 10 for your first successful build. This extension introduces nested lists and grading towards two opposing walls; it does not introduce near-wall resolution requirements for turbulence models.

Documentation: [R1], §5.4.6. The two-section example and numerical values are constructed for this part.

8. A patch has a name and a mesh type

A boundary patch groups exterior faces. The name is an identifier you choose; the mesh type describes the kind of patch. Neither alone prescribes the inlet velocity or the pressure at the outlet.

Patch nameMesh typeFaces included
inletpatchThe end face at x = 0
outletpatchThe end face at x = L
wallswallBoth y-faces and both z-faces

A fragment inside the boundary list, not a complete file:

inlet
{
    type patch;
    faces ((0 4 7 3));
}

The outer parentheses after faces hold a list of faces. The inner parentheses hold the four vertex labels of this one block face. The walls patch uses the same syntax but contains four faces.

Mesh description versus field condition

In the mesh dictionaryLater, in a field file
walls { type wall; ... }U may impose noSlip on the walls patch.
inlet { type patch; ... }U may prescribe a velocity there; p has its own condition.

The future 0/U and 0/p files will refer to these patch names. Part 3 explains those field conditions. For now, create no velocity or pressure file merely to make a meshing command run.

Why group four faces?
All four long faces have the same mesh type and will initially share their field conditions. Separate them into distinct patches later only when a boundary condition or measurement needs that distinction. Patch grouping changes identity, not cell resolution.

Documentation: [R1], §5.4.7; mesh constraints and types: [R3].

9. Walk around each face edge by edge

A face entry is a loop through four connected corners, not a set of four labels in arbitrary order. The table below uses outward-oriented loops for clarity. Together they account for all six exterior faces of the block.

LocationLoop in blockMeshDictOutward normalPatch
x = 0(0 4 7 3)−xinlet
x = L(1 2 6 5)+xoutlet
y = 0(0 1 5 4)−ywalls
y = H(3 7 6 2)+ywalls
z = 0(0 3 2 1)−zwalls
z = W(4 5 6 7)+zwalls
Comparison between an edge loop around a face and a crossed loop
Figure 5. Trace adjacent edges of the face. A crossed ordering does not represent the same boundary loop.

Important v14 distinction
The v14 guide permits either direction around a blockMeshDict boundary face, provided consecutive vertices follow connected edges. Outward ordering here is a teaching convention, not an extra parser requirement. The generated polyMesh uses its own consistent owner/neighbour face orientation.

For a check on this rectangular example, the cross product of successive edges in the inlet loop points in −x. Reversing that whole loop changes the hand calculation of its normal, but does not justify predicting a blockMesh failure. Crossing diagonals, omitting a face or using the wrong labels is a different issue.

Documentation: [R1], §5.4.7, especially the direction convention; generated face orientation: [R2].

10. The complete blockMeshDict

Save this entire listing as system/blockMeshDict. It has no omitted sections or line numbers. The minimal controlDict is in the next section.

FoamFile
{
    format      ascii;
    class       dictionary;
    object      blockMeshDict;
}

units [mm];

vertices
(
    (  0   0  0)   // 0
    (100   0  0)   // 1
    (100  10  0)   // 2
    (  0  10  0)   // 3
    (  0   0  5)   // 4
    (100   0  5)   // 5
    (100  10  5)   // 6
    (  0  10  5)   // 7
);

blocks
(
    hex (0 1 2 3 4 5 6 7) (40 10 5)
    simpleGrading (1 1 1)
);

boundary
(
    inlet
    {
        type patch;
        faces ((0 4 7 3));
    }

    outlet
    {
        type patch;
        faces ((1 2 6 5));
    }

    walls
    {
        type wall;
        faces
        (
            (0 1 5 4)
            (3 7 6 2)
            (0 3 2 1)
            (4 5 6 7)
        );
    }
);

Documentation: [R1], standard v14 syntax. This complete reference dictionary is an original teaching example.

11. Supply a minimal run-time context

OpenFOAM utilities initialise a run-time object. Supply system/controlDict even though you are not solving a flow. The following values are a mesh-only scaffold, not the time-step choice for the later CFD simulation.

FoamFile
{
    format      ascii;
    class       dictionary;
    object      controlDict;
}

application       blockMesh;
startFrom         startTime;
startTime         0;
stopAt            endTime;
endTime           1;
deltaT            1;
writeControl      timeStep;
writeInterval     1;
writeFormat       ascii;
writePrecision    10;
writeCompression  off;
timeFormat        general;
timePrecision     6;
runTimeModifiable yes;

What is being selected?

The shell command selects the program you execute. The application blockMesh; entry documents the purpose of this scaffold; it does not cause checkMesh to run blockMesh. Detailed time and output controls belong to Part 4.

What is still absent?

The standalone blockMesh and basic checkMesh workflow does not need fvSchemes, fvSolution, physical properties, U or p. Those files will be added when their consuming application needs them.

Do not run foamRun yet
A valid mesh is not a complete flow case. The goal at this stage is to generate and inspect polyMesh, then carry its patch names into the next part.

Documentation: [R5]; utility run-time construction and mesh-only reads: [R8]–[R9].

12. Generate, then inspect the real log

Prepare a new working directory

Use your own home directory, not the installed tutorial tree. Execute each step separately and stop on an error. If the named case already exists, inspect it before editing or choose a new name.

foamVersion
command -v blockMesh checkMesh foamDictionary
mkdir -p ~/cases/dictionary-training
cd ~/cases/dictionary-training
mkdir trainingChannel
cd trainingChannel
mkdir 0 constant system
vi system/blockMeshDict
vi system/controlDict

The version must identify Foundation release 14. Enter the full listings from sections 10 and 11. In vi, save and quit with :wq. An empty 0/ directory is sufficient at this stage.

Run one command at a time from the case root

set -o pipefail
blockMesh 2>&1 | tee log.blockMesh
checkMesh -constant 2>&1 | tee log.checkMesh

Run checkMesh only after mesh generation succeeds. Read the actual report for counts, dimensions and the final check summary. For the uniform rectangular reference mesh, the target is Mesh OK. plus the values in section 13.

A zero exit status is not enough
In the v14 checkMesh source, a report of failed checks can still be followed by return code 0. Read the textual result. Bash pipefail helps detect pipeline failures, but it cannot turn a reported mesh-quality failure into a nonzero status.

Optional extra checks: checkMesh -constant -allTopology -allGeometry. Do not add -meshQuality without its required system/meshQualityDict.

Documentation: [R8]–[R9]. The commands have been checked against v14 sources; run them on your installation.

13. Compare with independent predictions

This section contains the exact topological counts and geometric values of the one-block reference case. Check them against the output generated on your server.

QuantityExpected valueHow it is obtained
Bounding box in SI(0 0 0) – (0.1 0.01 0.005) mConvert millimetres to metres once.
Cells2,00040 × 10 × 5
Points2,70641 × 11 × 6
Internal faces5,35039×10×5 + 40×9×5 + 40×10×4
Boundary faces1,3002(10×5 + 40×5 + 40×10)
Total faces6,650Internal + boundary faces
Total volume5 × 10⁻⁶ m³0.1 × 0.01 × 0.005
Uniform cell volume2.5 × 10⁻⁹ m³Total volume / 2,000

Account for every boundary face

PatchGenerated facesBlock-face subdivision
inlet5010 × 5
outlet5010 × 5
walls1,2002(40 × 5) + 2(40 × 10)

The reference should be recognised as three-dimensional, with positive cell volumes and no nonempty unexpected boundary patch. Its axis-aligned cells have ideal orthogonality apart from round-off. Do not compare a changed or graded case against the uniform-cell-volume row.

Interpret “Mesh OK” correctly
It says that the checks performed did not fail. It does not establish physical boundary conditions, a suitable near-wall resolution, mesh-independent flow results or experimental agreement.

Documentation: counts are derived from the Cartesian product grid. Reported checks and their interpretation: [R9].

14. Read what blockMesh generated

ls constant/polyMesh
less constant/polyMesh/boundary
FileStored informationQuestion it answers
pointsGenerated point coordinatesWhere are the mesh vertices?
facesLists of generated point labelsWhich vertices surround each face?
ownerOne owning cell for each faceWhich cell owns this face?
neighbourA second cell for each internal faceWhat lies across an internal face?
boundaryPatch types and face rangesWhich exterior faces form each patch?

In the generated boundary file, nFaces is the number of cell faces assigned to a patch and startFace is its starting index in the mesh face list. Internal faces precede boundary faces. Expected face range for the reference patch order (other metadata may also appear):

inlet
{
    type        patch;
    nFaces      50;
    startFace   5350;
}

Two different label spaces
The labels 0-7 in your dictionary name block control vertices. The generated points file contains 2,706 points with mesh numbering. Do not interpret the first eight generated point labels as if they were your eight block-corner labels.

Modify the construction dictionary and regenerate the teaching mesh instead of manually changing connectivity files. By default, blockMesh can replace the existing polyMesh; preserve a separate case before trying variants on a completed simulation.

Documentation: [R2]; replacement behaviour: [R8]. The displayed count and starting index follow the reference topology.

15. Inspect geometry, not a flow solution

Use the ParaView reader and client/server connection established in the initial practical cases. The case must be accessible to the process that reads it: the server in a client/server session, or the local machine in a local session.

Create only the marker required by that reader

# Native OpenFOAM reader: no GUI is launched
paraFoam -touch
# Alternative: only for the ParaView built-in reader
paraFoam -builtin -touch

The native route creates trainingChannel.OpenFOAM; the built-in route creates trainingChannel.foam. Choose the route matching your configured reader, rather than trying to open both. The marker is an entry point, not a converted copy of the mesh.

A short visual inspection

ActionWhat to check
Open the marker and apply the readerThe case loads even though no flow fields have been created.
Select the volume mesh / mesh partsConfirm there is one connected duct, not just isolated end patches.
Show edges or wireframeDistinguish individual cells from the outer block edges.
Inspect bounds and orientationCheck x, y and z against section 13; camera rotation is not a unit check.
Select inlet, outlet and walls separatelyConfirm the grouping of the two end faces and four long faces.
Inspect a mid-depth sliceCompare the uniform baseline with the graded variant.

For the graded case, an x-y slice at z = 0.0025 m reveals the y-cell distribution. Use the display mode that shows cell edges. If the view appears unchanged after remeshing, reload the data using your reader’s refresh mechanism.

What you will not see yet
No velocity, pressure, streamlines or flow direction can be inferred from the mesh alone. The inlet/outlet names express your intended future setup; the mesher has not solved those conditions.

Documentation: [R7]; exact marker options and file extensions: [R10].

16. Change one thing, then explain it

Keep the uniform reference intact. Create a new case with only the two source dictionaries; this avoids mixing previous meshes or results into the experiment. Start in the reference case directory.

mkdir ../trainingChannel_xFine
mkdir ../trainingChannel_xFine/{0,constant,system}
cp system/blockMeshDict system/controlDict ../trainingChannel_xFine/system/
cd ../trainingChannel_xFine

Experiment A / refine only x

Change (40 10 5) to (80 10 5). Before running, write down the cell count, x-cell width and inlet face count. Generate and check the new mesh. Explain why a finer x-resolution does not change the number of inlet faces.

Experiment B / cluster towards the lower wall

Make another clean copy of the uniform reference. Retain (40 10 5) and replace the grading with (1 4 1). Predict which side becomes fine and which becomes coarse. Inspect a slice. Confirm that points, faces, cells and the bounding box retain their baseline counts or dimensions.

Experiment C / change geometry, not resolution

In a third fresh copy, change all four x = 100 coordinates to x = 200 while keeping the counts and uniform grading. Predict the volume and x-cell width. Explain why editing only two outlet vertices would change the shape rather than simply double its length.

The three questions after each change
What changed in the dictionary? What did I predict? What did the generated mesh actually show? A short answer to those three questions is sufficient; no formal validation report is required.

Use new directory names for each variant. Do not reuse a command that copies into an existing completed case without first checking its destination. Reuse the generation/check commands from section 12. Expected values are worked out in section 20.

Documentation: commands operate on your teaching copies. Dictionary effects: [R1].

17. Reading exercises: explain the file

A / read without executing

  1. In the reference file, which entry controls the physical height? Which entry controls the number of cells across that height? Why are these not the same setting?
  2. How many block faces are placed in walls? How many generated cell faces does that patch contain? Explain the difference.
  3. What changes when you replace simpleGrading (1 4 1) with simpleGrading (1 0.25 1)? What does not change?
  4. What is wrong with changing type patch; to type fixedValue; in the mesh inlet? Where does a prescribed velocity belong instead?
  5. Does the valid loop (3 7 4 0) describe the same block face as (0 4 7 3)? Is reversal alone an error for a v14 blockMesh boundary face?

B / classify the change

Proposed editYour classification
Change all x = 100 coordinates to x = 80.Geometry / topology / distribution / identity?
Replace (40 10 5) with (80 10 5).Geometry / topology / distribution / identity?
Replace y-grading 1 with 4.Geometry / topology / distribution / identity?
Rename inlet to feed without changing faces.Geometry / topology / distribution / identity?

Look for the consequence, not a password
Some edits affect more than one layer. Increasing a cell count changes the generated mesh topology as well as its spatial resolution. The useful answer identifies what is preserved and what must be regenerated.

C / find a fact in the official guide

Locate the v14 subsection that defines the expansion ratio and the one that states the rule for boundary-face direction. Record the subsection numbers and explain each rule in your own words. Use section 21 to navigate, then compare with section 20.

18. Independent task: a second channel

Create trainingChannel_independent in a new directory. Start with the geometry specification below, not by replacing numbers blindly in the completed reference. Draw the eight labelled corners before typing.

RequirementSpecification
Physical dimensionsL = 80 mm; H = 8 mm; W = 4 mm
Cell counts40 in x; 16 in y; 8 in z
Cell distributionUniform x and z; y end/start width ratio = 4
Boundary patchesinlet at x = 0; outlet at x = L; all other faces in walls
DimensionalityThree-dimensional; no empty patches
Files to constructsystem/blockMeshDict and the mesh-only controlDict

Before generating the mesh

Predict the bounding box in metres, total cells, total points, inlet faces and total volume. Identify the finer y-wall. Use the formula in section 6 to estimate the smallest and largest y-cell widths.

Then test your construction

Run blockMesh, read its output, then run checkMesh. Compare with your predictions and inspect a slice. Explain the file from top to bottom without relying on its comments.

Completion criterion
The intended duct is generated; mesh checks report no failure; counts and dimensions agree with your predictions; every exterior face belongs to the intended patch; and you can explain all five main dictionary sections.

One optional extension

Split walls into lowerWall for y = 0 and otherWalls for the remaining three long faces. Do not duplicate or omit a face. Predict which mesh counts stay unchanged and which patch counts change.

The exercise deliberately does not ask for a velocity field, a turbulence model or mesh-independence evidence. Those are separate learning objectives. Numerical checkpoints appear in section 20.

19. Diagnose one cause at a time

Read the first relevant error in context: application, file, entry and expected type. Correct one cause and rerun the same utility. The descriptions below are diagnostic categories, not invented verbatim console messages.

SymptomFirst thing to check
Dictionary cannot be foundRun from the case root; verify system/blockMeshDict and exact filename case.
controlDict cannot be readCreate the mesh-only context in section 11; do not add random solver files.
Unexpected token or end of fileCheck paired braces/parentheses and the semicolon after each list entry.
Point label out of rangeOnly labels 0-7 exist in this vertices list; inspect every face and the hex entry.
Inside-out, twisted or invalid blockCompare the vertex coordinates and hex connectivity with section 4.
An unexpected defaultFaces patchFind an exterior face missing from boundary. Check its type and face count.
Dimensions wrong but counts rightCheck units and scale; counts do not detect a length conversion error.
The wrong wall is refinedRead grading in the local direction; E is last width / first width.
The displayed mesh did not changeCheck the case path, rerun blockMesh and reload the correct reader data.

A missed face can be more dangerous than a syntax error
Omitted faces can be collected into a default patch. A generated mesh is therefore not proof that the boundary matches your intention. This baseline explicitly lists all six exterior block faces.

Deliberate error practice

In a fresh teaching copy only, replace vertex label 7 with 8 in one patch face. Run blockMesh, identify the failing patch/label, then repair it. As a separate exercise, omit one exterior face and inspect the warning/default-patch behaviour. Restore the complete boundary afterwards.

Documentation: [R1], §5.4.7; implementation and diagnostics: [R8]–[R9].

20. Answer notes and numerical checks

The three guided experiments

CaseKey expected changes
A: x refinement4,000 cells; Δx = 1.25 mm; inlet still 50 faces; unchanged bounding box.
B: y grading = 42,000 cells and unchanged topology; finer near y = 0; Δy ≈ 0.4542 to 1.8170 mm.
C: L doubled2,000 cells; Δx = 5 mm; volume = 1 × 10⁻⁵ m³; maximum x = 0.2 m.

Reading exercise answers

  1. The y-coordinates set H; the second cell-count entry sets Ny.
  2. Four block faces become 1,200 cell faces.
  3. The grading reverses while the counts, domain and patch assignment stay fixed.
  4. fixedValue is a field condition, not the intended generic mesh-patch type; the velocity condition belongs in 0/U.
  5. Both loops identify the inlet face; reversal alone is allowed in blockMesh‘s boundary list.

Changing the length changes geometry. Increasing Nx changes resolution and generated topology. Changing grading changes point placement while preserving this mesh’s connectivity. Renaming a patch changes identity; later field files must use the new name. The requested guide sections are 5.4.5 and 5.4.7.

Independent channel (section 18)

CheckpointExpected result
Bounding box in SI(0 0 0) – (0.08 0.008 0.004) m
Cells / points5,120 / 6,273
Internal / boundary / total faces14,272 / 2,176 / 16,448
Patch face countsinlet: 128; outlet: 128; walls: 1,920
Volume / x-cell width2.56 × 10⁻⁶ m³ / 2 mm
y widths, start to end0.2287 to 0.9147 mm; finer near y = 0
Optional patch splitlowerWall: 320; otherWalls: 1,600; no change to total counts

These are the checkpoints for the independent channel. Round-off may affect the last digits of geometric values; the exact topological counts should agree.

21. Use the guide as a working tool

Start with the requirement, identify the relevant entry, read the v14 subsection, and compare one matching tutorial pattern. Do not replace the entire dictionary when only one feature is unfamiliar.

Your questionOpenFOAM v14 User Guide
Where are mesh data stored?§5.2 – Mesh files [R2]
Which coordinate units apply?§5.4.2 – Units and scaling [R1]
How are vertices and blocks ordered?§§5.4.3 and 5.4.5 [R1]
What does grading mean?§§5.4.5–5.4.6 [R1]
How are boundary faces assigned?§5.4.7, plus §5.3 for patch types [R1, R3]
How do I inspect dictionary entries?§4.7.2 – foamDictionary [R6]

Inspect the case structurally

foamDictionary system/blockMeshDict -entry units -value
foamDictionary system/blockMeshDict -entry vertices -value
foamDictionary system/blockMeshDict -entry blocks -value
foamDictionary system/blockMeshDict -entry boundary -value

foamDictionary confirms what an entry contains. It is not a replacement for blockMesh‘s topology construction or checkMesh‘s geometrical checks.

Find examples in the installed tutorial tree

find "$FOAM_TUTORIALS" -type f -name blockMeshDict
blockMesh -help
checkMesh -help

Open a relevant file with less and identify only the pattern you need. Some tutorial meshes use shared resource files instead of a local blockMeshDict; inspect their run script or the utility’s -dict argument. Do not edit the installed examples.

Documentation: [R1], §5.4.12; dictionary queries: [R6]; available utility options: [R8]–[R9].

References and the next step

Use Foundation v14 references for this series. The links below point to the pages or source files consulted when preparing this part; other OpenFOAM distributions may use different options.

Ready for Part 3
Keep the uniform reference as trainingChannel with inlet, outlet and walls. Part 3 will introduce the field files and the initial and boundary conditions. You now have a mesh to which those fields can refer.

Original diagrams, numerical examples and teaching explanations. Previous part: OpenFOAM 14 – Case Anatomy and Dictionary Language. This is an independent teaching article, not an official OpenFOAM publication. All parts are in the Learning OpenFOAM 14 project.

#blockMesh #CFD #mesh #OpenFOAM