FMS
v0.1
Field and Mesh Specification

This file provides a brief description of the FMS data format/API proposed by the ECP/CEED codesign center to represent unstructured highorder meshes with general highorder finite element fields defined on them.
Developers may also want to consult the automatically updated Doxygen documentation.
The data described by FMS is a collection of:
This separation of mesh geometry and topology is important in many applications (e.g. those with moving meshes) and allows the FMS format to handle general highorder meshes in a simple and uniform way.
Note that the geometry of the mesh, described by the coordinates of the vertices, for linear meshes, or the coordinates of the nodes for highorder meshes is specified itself as just another finite element field, called nodes or coordinates (for example as vector field in an H1space of appropriate order).
The mesh topology, described by the type FmsMesh
below, is represented by the following interconnected mesh entities:
The topology does not include geometric or finite element information, but does include relations between the entities and their orientation with respect to reference configurations.
The topology can also be split into domains and components which form a decomposition (e.g. for parallel computations), or select a subset of physical interest, respectively.
In FMS, the Mesh topology is described by objects of type FmsMesh
, which can be constructed with FmsMeshConstruct()
and deleted with FmsMeshDestroy()
.
FMS makes the following assumptions about the mesh:
The second assumption provides a set of downward adjacencies which allows easy reconstruction of relations like elementvertex, while providing flexibility for algorithms that need to loop over faces and edges.
More specifically, a mesh entity is described by a tuple of its side entity indices. For an entity of dimension d
, its side entities are its boundary entities of dimension d1
.
For FMS_TRIANGLE
and FMS_QUADRILATERAL
, the edges (sides), "abc"/"abcd" and the vertices "012"/"0123" are ordered counterclockwise, as illustrated in the following diagram:
For 3D entities, the ordering of the edges inside the faces should follow the counterclockwise ordering when looking the face from outside. This rule is followed by the choices given below.
For FMS_TETRAHEDRON
, the faces (sides), "ABCD", the edges, "abcdef", and the vertices, "0123" are ordered as follows:
For example, vertex "0" has coordinates (x,y,z)=(0,0,0)
, vertex "1" has coordinates (1,0,0)
, etc.
For FMS_HEXAHEDRON
, the faces (sides), "ABCDEF", the edges, "abcdefghijkl" and the vertices, "01234567", are ordered as follows:
For example, vertex "0" has coordinates (x,y,z)=(0,0,0)
, vertex "6" has coordinates (1,1,1)
, etc.
Mesh domains describe sets of interconnected mesh entities (0d, 1d, 2d and 3d). All entities in the domain are enumerated locally.
Each mesh domain can be viewed as its own independent mesh, as it provides full description of the entities inside it (the face of all volumes are described as 2entities, the edges of all faces are described as 1entities, etc.)
A typical example to keep in mind is parallel computations, where an MPI tasks can contain one (or several) domains, which can be processed independently in the interior. Connections between domains are described using shared entities. Domains are assigned a string name and an integer id. Thus, a domain is identified uniquely by the tuple: (name, id, partitionid) where the partition id is the one assigned to the containing mesh. The following picture shows a 2D mesh partitioned between two processes and then each process has two domains.
In FMS, domains are described using objects of type FmsDomain
which can only exist as part of an FmsMesh
; they are created using the FmsMeshAddDomain()
function. To describe the mesh entities inside the domain, one uses the functions FmsDomainSetNumVertices()
, FmsDomainSetNumEntities()
, FmsDomainAddEntities()
, etc.
Mesh components are regions of physical interest defined across the mesh domains, such as materials, sections of the boundary, different parts in fluidstructure interaction, etc. The subset of the component on each domain is a set of entities, which is called a "part". Each part is described as a list of entity indices which point to entities of the associated domain. All entities in the component must have (i) the same dimension and (ii) specified orientation (relative to the entity as described in its domain).
Note that different components can overlap and be of different dimensions. Typically, the whole is represented by a special component of all elements (3entities) on all domains. This is the component, for example, on which the mesh nodes will be defined (see below).
In order to facilitate the definition of fields on the component, the following additional data can be stored in every part of the component: for all lower dimensional entities that are boundary to the main entities of the part, define an array that maps the local (to the part) indices to the domainindices. These arrays plus the main array (the one describing the highest dimensional entities of the component) define local numberings of all entities inside each part. These numberings will be used to define the ordering of the degrees of freedom of a field. When the main entity array is NULL
(indicating that all entities in the domain are used) then the lower dimensional entities will also be NULL
because there is no need to have local numbering of the entities  the original numbering defined by the domain can be reused.
In addition to the parts, a component also stores relations to other components. A relation to a component of lower or higher dimension indicates a boundary or interface relation, i.e. the lower dimensional component describes a subset of the boundary entities of the higher dimensional component. A relation to another component of the same dimension is acceptable but has no specified meaning.
A component has an associated coordinates or nodes field, of type FmsField
, which may be NULL
. Mesh tags (discussed below) are defined on the set of all main entities in a mesh component.
Discrete fields are defined on mesh components. Unlike tags, discrete fields generally associate data not only with the entities described by the mesh component but also with the lowerdimensional boundary entities of the main component entities.
In FMS, components are described using objects of type FmsComponent
which only exist as part of an FmsMesh
and are created using the FmsMeshAddComponent()
function. Parts and their entities can be added to the component with the functions FmsComponentAddPart()
, FmsComponentAddPartEntities()
, FmsComponentAddRelation()
, etc.
A mesh tag is an array of integers describing the main entities in a given component. Optionally, the integer tags can be assigned string descriptions.
Tags could be used to mark different boundary conditions, different materials in the mesh, store the orders (polynomial degrees) associated with the component entities in variableorder discrete spaces, etc.
Each tag naturally defines a nonoverlapping decomposition of the associated component. The array with the integer tags is ordered partbypart within the mesh component.
In FMS, tags are described using objects of type FmsTag
which exist only as a part of a mesh and can be created using the FmsMeshAddTag()
function and described by the functions FmsTagSetComponent()
, FmsTagSet()
, FmsTagAddDescriptions()
, etc.
The fields, described by the type FmsField
below, are highorder finite element functions given in terms of their degrees of freedom associated with the interior of each of the mesh entities. These fields can be specified only on mesh components, and can describe any scalar or vector function in the de Rham complex (H1, H(curl), H(div) and L2 elements).
As noted above, the coordinates of the mesh nodes, specifying the actual mesh shape in physical space, are just a special field on the whole mesh.
In FMS each field is specified by defining a FmsFieldDescriptor
that contains the associated mesh component, the basis type describing the field and type of the field itself i.e. continuous, discontinuous etc. Two options are available for storing vector field data, either by dimension, FMS_BY_VDIM
or by nodes FMS_BY_NODES
. In the former, the pair of indices (i,j)
of degree of freedom i
and vector component j
are mapped to a 1D array by the formula i*vdim+j
; in latter choice (FMS_BY_NODES
), the indices (i,j)
are mapped using the formula i+num_dofs*j
.
FMS fields and their descriptors are stored in, and only exist as part of, objects of type FmsDataCollection
which in turn can be created on top of an FmsMesh
object using the function FmsDataCollectionCreate()
. Objects of types FmsField
and FmsFieldDescriptor
can be created with the functions FmsDataCollectionAddFieldDescriptor()
and FmsDataCollectionAddField()
.
Below is a complete example of using the FMS interface to describe a simple mesh.