As well as being able to generate meshes in NekMesh, we seek to make NekMesh compatible
with multiple commonly-used file formats, enabling users to create meshes in their chosen
mesh generation software, before either elevating their order in NekMesh or using it as is.
Some file formats provide an API for reading from (and writing to) them; this includes .ccm
with CCMIO and .cgns with CGNS Mid-Level Library. Other formats such as .gmsh do not,
so we must manually read the file with stringstream
. Once the required information (such as
node coordinates, elements nodes, boundary conditions etc.) has been read from the file,
however, the process is the same:
For each node we must first create a node shared pointer (NodeSharedPtr
) append it to
m_node
and insert it into vertexSet
eg.
1NodeSharedPtr newNode = std::make_shared<Node>(id, x, y, z); 2m_mesh->m_node.push_back(newNode); 3m_mesh->m_vertexSet.insert(newNode);
...ensuring that the node IDs all comply with the Prism and Pyramid rules (section 17.2.2).
We must then append an ElementSharedPtr for each element (internal and boundary), eg.
1ElementSharedPtr E = GetElementFactory().CreateInstance(elType, conf, 2nodeList, tags); m_mesh->m_element[E->GetDim()].push_back(E);
Once the elements and nodes have been correctly created, the following functions are called sequentially to process this information into the NekMesh format.
1ProcessEdges(); 2ProcessFaces(); 3ProcessElements(); 4ProcessComposites();
Information about the CGNS Standard Interface Data Structure (SIDS) can be
found at https://cgns.github.io/CGNS_docs_current/sids. This converter makes
use of the CGNS Mid-Level Library and information about that can be found at
https://cgns.github.io/CGNS_docs_current/midlevel.We will summarise the key points about
the CGNS standard.
Every file will contain at least one zone, which contains information about coordinates and the mesh. Each zone contains at least one base, which contain information about the information about the dimensionality of the domain (fig. ??).
Elements are stored in sections where they are grouped by element type in the case of
SEPARATED CGNS files or all the elements are grouped together in the case of a
MIXED CGNS file. Depending on the file format, the InputCGNS.cpp
either uses
ExtractMixedElemInfo() or ExtractSeparatedElemInfo(). In both case, an array
ElementConnectivity
is read in, containing the node IDs for each element (in the MIXED
format the element type must also be specified for each element). Each function takes the
ElementConnectivity
array and generates a vector elemInfo
which contains the type and
node list for each element.
The function ReadFaces converts from elemInfo
into a face representation, where each
element is defined by its face (ElementFaces
), each face is defined by its nodes (FaceNodes
),
and the boundary element faces of the mesh are stored in BndElementFaces
. These three
variables are required for the next function ResetNodes
and allows us to re-use a large section
of code from the InputStar
converter.
The final step that must be mentioned is the fact that CGNS and NekMesh use different
conventions for the order in which to list higher order nodes. In the functions GenElement2D
and GenElement3D
, we must use mappings generated by CGNSReordering
to map between the
diffent conventions. Although these could be produced algorithmically (and one would want to
if CGNS supported orders higher than 4th), for the moment they have been hard-coded in
by manually comparing the node orderings in the CGNS SIDS [3] and NekMesh
17.2.3.