This section provides a specification of the way the OpenFOAM C++ 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, OpenFOAM 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 OpenFOAM will run using it. This is unfortunate but we make no
apology for OpenFOAM simply adopting good practice to ensure the
mesh is valid; otherwise, the solution is flawed before the run has even
begun.
By default OpenFOAM 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
OpenFOAM as a polyMesh. It is described in further detail in ?? of the
Programmer’s Guide, but 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 OpenFOAM library therefore provides cellShape
tools to manage conventional mesh formats based on sets of pre-defined cell
shapes.
Before describing the OpenFOAM mesh format, polyMesh, and the cellShape
tools, we will first set out the validity constraints used in OpenFOAM. The
conditions that a mesh must satisfy are:
A point is a location in 3-D space, defined by a vector in units of metres ().
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 containtwo different points at an exactly identical position nor any point that is not partat least one face.
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 5.1.
Figure 5.1:
Face area vector from point numbering on the face
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.
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.
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.
The constant directory contains a full description of the case polyMesh in a
subdirectory 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:
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.;
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.;
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;
neighbour
a list of neighbour cell labels;
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 is the index into the face list of the first face in the patch,
and nFaces is the number of faces in the patch.
Note that if the user wishes to know how many cells are in their domain, thereis a note in the FoamFile header of the owner file that contains an entry fornCells.
We shall describe the alternative cellShape tools that may be used particularly
when converting some standard (simpler) mesh formats for the use with
OpenFOAM 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
OpenFOAM 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 OpenFOAM are shown in 5.2. 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 5.2. 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 is a single
shape. Moreover it is unnecessary to use duplicate points in OpenFOAM
since the available shapes in OpenFOAM 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
OpenFOAM 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 OpenFOAM 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 patch type and axi-symmetric
problems use the wedge type. The use of both are described in 5.2.2 and the
generation of wedge geometries for axi-symmetric problems is discussed in
5.3.3.