17.3 Input Modules

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:

  1. 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).

  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);
  3. 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();

17.3.1 StarCCM+ .ccm input (InputStar.cpp)

17.3.2 Gmsh .msh input (InputGmsh.cpp)

17.3.3 CGNS .cgns input (InputCGNS.cpp)

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. ??).


PIC

Figure 17.13 CGNS database hierarchy. Image from cgns.github.io


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.