[[sec_blockMeshDict]]
=== Mesh description
(((mesh,description)))

This section provides a specification of the way the {project} {cpp} classes
handle a mesh. The mesh is an integral part of the numerical solution and must
satisfy certain criteria to ensure a valid, and hence accurate, solution.
During any run, {project} checks that the mesh satisfies a fairly stringent set
of validity constraints and will cease running if the constraints are not
satisfied. The consequence is that a user may experience some frustration in
`correcting' a large mesh generated by third-party mesh generators before
{project} will run using it. This is unfortunate but we make no apology for
{project} simply adopting good practice to ensure the mesh is valid; otherwise,
the solution is flawed before the run has even begun.

By default {project} defines a mesh of arbitrary polyhedral cells in 3-D,
bounded by arbitrary polygonal faces, 'i.e.' the cells can have an unlimited
number of faces where, for each face, there is no limit on the number of edges
nor any restriction on its alignment. A mesh with this general structure is
known in {project} as a `polyMesh`.(((`polyMesh` class)))(((class,`polyMesh`)))
It is sufficient to mention here that this type of mesh offers great freedom in
mesh generation and manipulation in particular when the geometry of the domain
is complex or changes over time. The price of absolute mesh generality is,
however, that it can be difficult to convert meshes generated using
conventional tools. The {project} library therefore provides `cellShape` tools
to manage conventional mesh formats based on sets of pre-defined cell shapes.

==== Mesh specification and validity constraints
(((mesh,specification))) (((mesh,validity constraints)))

Before describing the {project} mesh format, `polyMesh`, and the `cellShape`
tools, we will first set out the validity constraints used in {project}. The
conditions that a mesh must satisfy are:

===== Points

A point is a location in 3-D space, defined by a vector in units of metres
(math:[\unit{m}]). The points are compiled into a list and each point is
referred to by a label, which represents its position in the list, starting
from zero. 'The point list cannot contain two different points at an exactly
identical position nor any point that is not part at least one face.'

===== Faces

A face is an ordered list of points, where a point is referred to by its label.
The ordering of point labels in a face is such that each two neighbouring
points are connected by an edge, 'i.e.' you follow points as you travel around
the circumference of the face. Faces are compiled into a list and each face is
referred to by its label, representing its position in the list. The direction
of the face normal vector is defined by the right-hand rule, 'i.e.' looking
towards a face, if the numbering of the points follows an anti-clockwise path,
the normal vector points towards you, as shown in <<fig_faceNumbering>>.

[[fig_faceNumbering]]
.Face area vector from point numbering on the face
image::images/mesh_faceNumbering.{gfx-fmt}[]

There are two types of face:

*Internal faces*::
  Those faces that connect two cells (and it can never be more than two). For
  each internal face, the ordering of the point labels is such that the face
  normal points into the cell with the larger label, 'i.e.' for cells 2 and 5,
  the normal points into 5;
*Boundary faces*::
  Those belonging to one cell since they coincide with the boundary of the
  domain. A boundary face is therefore addressed by one cell(only) and a
  boundary patch. The ordering of the point labels is such that the face normal
  points outside of the computational domain.

Faces are generally expected to be convex; at the very least the face centre
needs to be inside the face. Faces are allowed to be warped, 'i.e.' not all
points of the face need to be coplanar.

===== Cells

A cell is a list of faces in arbitrary order. Cells must have the properties
listed below.

*Contiguous*::
  The cells must completely cover the computational domain and are must not
  overlap one another.
*Convex*::
  Every cell must be convex and its cell centre inside the cell.
*Closed*::
  Every cell must be 'closed', both geometrically and topologically where:
  - geometrical closedness requires that when all face area vectors are
    oriented to point outwards of the cell, their sum should equal the zero
    vector to machine accuracy;
  - topological closedness requires that all the edges in a cell are used by
    exactly two faces of the cell in question.
*Orthogonality*::
For all internal faces of the mesh, we define the centre-to-centre vector as
that connecting the centres of the 2 cells that it adjoins oriented from the
the centre of the cell with smaller label to the centre of the cell with larger
label. The orthogonality constraint requires that for each internal face, the
angle between the face area vector, oriented as described above, and the
centre-to-centre vector must always be less than 90&deg;.

===== Boundary

A boundary is a list of patches, each of which is associated with a boundary
condition. A patch is a list of face labels which clearly must contain only
boundary faces and no internal faces. The boundary is required to be closed,
'i.e.' the sum all boundary face area vectors equates to zero to machine
tolerance.

[[sec_polyMesh]]
==== The `polyMesh` description

The dirname:constant[] directory contains a full description of the case
`polyMesh` (((`polyMesh` class)))(((class,`polyMesh`))) in a subdirectory
filename:polyMesh[].(((filename:polyMesh[] directory)))
(((directory,filename:polyMesh[]))) The `polyMesh` description is based around
faces and, as already discussed, internal cells connect 2 cells and boundary
faces address a cell and a boundary patch. Each face is therefore assigned an
`owner' cell and `neighbour' cell so that the connectivity across a given face
can simply be described by the owner and neighbour cell labels. In the case of
boundaries, the connected cell is the owner and the neighbour is assigned the
label `-1'. With this in mind, the I/O specification consists of the following
files:

filename:points[]::
  (((filename:points[],dictionary)))(((dictionary,filename:points[]))) a list
  of vectors describing the cell vertices, where the first vector in the list
  represents vertex 0, the second vector represents vertex 1, 'etc.';
filename:faces[]::
  (((filename:faces[],dictionary)))(((dictionary,filename:faces[]))) a list of
  faces, each face being a list of indices to vertices in the points list,
  where again, the first entry in the list represents face 0, 'etc.';
filename:owner[]::
  (((filename:owner[],dictionary)))(((dictionary,filename:owner[]))) a list of
  owner cell labels, the index of entry relating directly to the index of the
  face, so that the first entry in the list is the owner label for face 0, the
  second entry is the owner label for face 1, 'etc.';
filename:neighbour[]::
  (((filename:neighbour[],dictionary)))(((dictionary,filename:neighbour[]))) a
  list of neighbour cell labels;
filename:boundary[]::
  (((filename:boundary[],dictionary)))(((dictionary,filename:boundary[]))) a
  list of patches, containing a dictionary entry for each patch, declared using
  the patch name, 'e.g.'
+
-------------------------------------------------------------------------------
movingWall
{
    type patch;
    nFaces 20;
    startFace 760;
}
-------------------------------------------------------------------------------
+
The `startFace` (((`startFace` keyword)))(((keyword,`startFace`))) is the index
into the face list of the first face in the patch, and `nFaces` (((`nFaces`
keyword)))(((keyword,`nFaces`))) is the number of faces in the patch.


'Note that if the user wishes to know how many cells are in their domain,
there is a' `note` 'in the' `FoamFile` 'header of the' filename:owner[] 'file
that contains an entry for' `nCells`.

==== The `cellShape` tools

We shall describe the alternative `cellShape` tools that may be used
particularly when converting some standard (simpler) mesh formats for the use
with {project} library.

The vast majority of mesh generators and post-processing systems support only a
fraction of the possible polyhedral cell shapes in existence. They define a
mesh in terms of a limited set of 3D cell geometries, referred to as 'cell
shapes'. The {project} library contains definitions of these standard shapes,
to enable a conversion of such a mesh into the `polyMesh` format described in
the previous section.

The `cellShape` models supported by {project} are shown in <<tab_cellShapes>>.
The shape is defined by the ordering of point labels in accordance with the
numbering scheme contained in the shape model. The ordering schemes for points,
faces and edges are shown in <<tab_cellShapes>>. The numbering of the points
must not be such that the shape becomes twisted or degenerate into other
geometries, 'i.e.' the same point label cannot be used more that once in a
single shape. Moreover it is unnecessary to use duplicate points in {project}
since the available shapes in {project} cover the full set of degenerate
hexahedra.

The cell description consists of two parts: the name of a cell model and the
ordered list of labels. Thus, using the following list of points

-------------------------------------------------------------------------------
8
(
    (0 0 0)
    (1 0 0)
    (1 1 0)
    (0 1 0)
    (0 0 0.5)
    (1 0 0.5)
    (1 1 0.5)
    (0 1 0.5)
)
-------------------------------------------------------------------------------

A hexahedral cell would be written as:

-------------------------------------------------------------------------------
(hex 8(0 1 2 3 4 5 6 7))
-------------------------------------------------------------------------------

Here the hexahedral cell shape is declared using the keyword `hex`. Other
shapes are described by the keywords listed in <<tab_cellShapes>>.

[[tab_cellShapes]]
.Vertex, face and edge numbering for ++cellShape++s
[grid="none",frame="topbot"]
|==============================================================================
| image:images/mesh_hexNumbering.{gfx-fmt}[]
| (a) Hexahedron: keyword `hex`
| image:images/mesh_wedgeNumbering.{gfx-fmt}[]
| (b) Wedge: keyword `wedge`
| image:images/mesh_prismNumbering.{gfx-fmt}[]
| (c) Prism: keyword `prism`
| image:images/mesh_pyrNumbering.{gfx-fmt}[]
| (d) Pyramid: keyword `pyr`
| image:images/mesh_tetNumbering.{gfx-fmt}[]
| (e) Tetrahedron: keyword `tet`
| image:images/mesh_tetWedgeNumbering.{gfx-fmt}[]
| (f) Tetrahedron wedge: keyword `tetWedge`
|==============================================================================

==== 1- and 2-dimensional and axi-symmetric problems
(((mesh,1-dimensional))) (((mesh,1D))) (((mesh,2-dimensional)))
(((mesh,2D))) (((mesh,axi-symmetric))) (((1-dimensional mesh)))
(((1D mesh))) (((2-dimensional mesh))) (((2D mesh)))
(((axi-symmetric mesh)))

{project} is designed as a code for 3-dimensional space and defines all meshes
as such. However, 1- and 2- dimensional and axi-symmetric problems can be
simulated in {project} by generating a mesh in 3 dimensions and applying
special boundary conditions on any patch in the plane(s) normal to the
direction(s) of interest. More specifically, 1- and 2- dimensional problems use
the `empty` (((`empty`,boundary condition)))(((boundary condition,`empty`)))
patch type and axi-symmetric problems use the `wedge`
(((`wedge`,boundary condition)))(((boundary condition,`wedge`))) type. The use
of both are described in <<sec_baseTypes>> and the generation of wedge
geometries for axi-symmetric problems is discussed in
<<sec_blocksWithFewerVertices>>.
