2. HOPR HDF5 Curved Mesh Format
Authors: Florian Hindenlang, Thomas Bolemann, Tobias Ott, Stephen Copplestone, Marcel Pfeiffer, Patrick Kopper
Last modified: November 23, 2023
2.1. Introduction and Main Idea Behind the Mesh Format
The High Order Preprocessor (HOPR) is able to generate high order unstructured 3D meshes, including tetrahedra, pyramids, prisms and hexahedra. The HDF5 library (http://www.hdfgroup.org/) allows to use parallel MPI-I/O, thus the mesh format is designed for a fast parallel read-in, using large arrays. There is also the GUI HDFView to browse h5 files.
An important feature is that the elements are ordered along a space-filling curve. This allows a simple domain decomposition during parallel read-in, where one simply divides the number of elements by the number of domains, so that each domain is associated with a contiguous range of elements. That means one can directly start the parallel computation with an arbitrary number of domains (\(\geq\) number of elements) and always read the same mesh file.
For each element, the neighbor connectivity information of the element sides and the element node information (index and position) are stored as a package per element, allowing to read contiguous data blocks for a given range of elements. To enable a fast parallel read-in, the coordinates of the same physical nodes are stored several times, but can be still associated by a unique global node index.
Notes:
Array-indexing starts at 1! (Fortran/Matlab Style)
Element connectivity is based on CGNS unstructured mesh standard (CFD general notation system, http://cgns.sourceforge.net), see Section Element Corners, Sides
The polynomial degree \(N_{geo}\) of the curved element mappings is globally defined. Straight-edged elements are found for \(N_{geo}=1\).
Only the nodes for the volume element mapping and no surface mappings are stored.
Curved node positions in reference space are uniform for all element types (see Section Element High Order Nodes).
Data types: we use 32bit INTEGER and 64bit REAL (double precision), if not stated differently.
HOPR generates *_mesh.h5 files. You can find examples of the mesh file by executing the tutorials in HOPR, and you can browse the files using HDFView.
2.2. Global Attributes
These attributes are defined globally for the whole mesh as given in table Table 2.1. For a mesh with elements having only straight edges, the polynomial degree of the element mapping is Ngeo\(=N_{geo}=1\). A mesh with curved elements has a fixed polynomial degree \(N_{geo}>1\) for all elements.
Attribute |
Data type |
Description |
---|---|---|
Version |
REAL |
Mesh File Version |
Ngeo \(\geq 1\) |
INTEGER |
Polynomial degree \(N_{geo}\) of element mapping, used to determine the number of nodes per element |
nElems |
INTEGER |
Total number of elements in mesh |
nSides |
INTEGER |
Total number of sides (or element faces) in mesh |
nNodes |
INTEGER |
Total number of nodes in mesh |
nUniqueSides |
INTEGER |
Total number of geometrically unique sides in the mesh |
nUniqueNodes |
INTEGER |
Total number of geometrically unique nodes in the mesh |
nBCs |
INTEGER |
Size of the Boundary Condition list |
FEMconnect |
STRING “ON”/”OFF” |
“ON” if FEM edge and vertex connection have been built and written to file. |
only for FEMconnect=”ON”: |
||
⮡ nEdges |
INTEGER |
Total number of entries in the EdgeInfo array (=sum over elements of nEdge(ElemType)) |
⮡ nVertices |
INTEGER |
Total number of entries in the VertexInfo array (=sum over elements of nVertices(ElemType)) |
⮡ nUniqueEdges |
INTEGER |
Total number of geometrically unique edges in the mesh |
⮡ nFEMSides |
INTEGER |
Total number of topologically (includes periodicity) unique sides in the mes (needed for a FEM solver) |
⮡ nFEMEdges |
INTEGER |
Total number of topologically (includes periodicity) unique edges in the mesh (needed for a FEM solver) |
⮡ nFEMEdgeConnections |
INTEGER |
Size of EdgeConnectInfo |
⮡ nFEMVertices |
INTEGER |
Total number of topologically (includes periodicity) unique vertices in the mesh (needed for a FEM solver) |
⮡ nFEMVertexConnections |
INTEGER |
Size of VertexConnectInfo |
2.3. Data Arrays
The mesh information is organized in arrays. The data is always stored in blocks for each element, which results in storing it multiple times. However, this way, each processor has a defined, non overlapping, range of geometry and connectivity information, where it can perform IO operations, minimizing the need of communication between processors.
The ElemInfo array is the first to read, since it contains the data range of each element in the SideInfo, EdgeInfo, VertexInfo and NodeCoords / GlobalNodeIDs arrays.
Array Name |
Description |
Type |
Size |
---|---|---|---|
ElemInfo |
Start\End positions of element data in SideInfo /NodeCoords |
INTEGER |
(1:6,1:nElems\(^*\)) |
SideInfo |
Side Data / Connectivity information |
INTEGER |
(1:5,1:nSides\(^*\)) |
EdgeInfo |
Element Edge information and offsets in EdgeConnectInfo |
INTEGER |
(1:3,1:nEdges\(^*\)) |
NodeCoords |
Node Coordinates |
REAL |
(1:3,1:nNodes\(^*\)) |
GlobalNodeIDs |
Globally unique node index |
INTEGER |
(1:nNodes\(^*\)) |
BCNames |
List of user-defined boundary condition names (max. 255 Characters) |
STRING |
(1:nBCs) |
BCType |
Four digit boundary condition code |
INTEGER |
(1:4,1:nBCs) |
ElemBarycenters |
Barycenter location of each element |
REAL |
(1:3,1:nElems\(^*\)) |
ElemWeight |
Element Weights for domain decomposition (=1 by default) |
REAL |
(1:nElems\(^*\)) |
ElemCounter |
mesh statistics (no. of elements of each element type) |
INTEGER |
(1:2,1:11) |
only for FEMconnect=”ON”: |
|||
⮡ FEMElemInfo |
Start\End positions of element data in EdgeInfo/VertexInfo |
INTEGER |
(1:4,1:nElems\(^*\)) |
⮡ EdgeConnectInfo |
Connectivity information for each element edge (needed for a FEM solver) |
INTEGER |
(1:2,1:nFEMEdgeConnections) |
⮡ VertexInfo |
Element Vertex Data information and and offsets in VertexConnectInfo |
INTEGER |
(1:3,1:nVertices\(^*\)) |
⮡ VertexConnectInfo |
Connectivity information for each element vertex (needed for a FEM solver) |
INTEGER |
(1:2,1:nFEMVertexConnections) |
2.3.1. Example 3D Mesh
In the following sections, we explain the array definitions and show an example, which refers to the mesh in Fig. 2.1 with straight-edges, so \(N_{geo}=1\). There is one element of each type, a tetrahedron, a pyramid, a prism and a hexahedron, four elements in total. Corner nodes and element sides have unique indices.
The global attributes of the mesh are shown in Table 2.3.
Ngeo |
1 |
nElems |
4 (Prism,Hex,Tet,Pyra) |
nBCs |
4 |
nSides |
20 (=5+6+4+5) |
nUniqueSides |
16 |
nFEMSides |
16 |
nEdges |
35 |
nUniqueEdges |
22 |
nFEMEdges |
22 |
nNodes |
23 (=6+8+4+5) |
nUniqueNodes |
11 |
nFEMVertices |
11 |
2.3.2. Element Information (ElemInfo)
Name in file: |
ElemInfo |
Type: |
INTEGER, Size: Array(1:6,1:nElems\(^*\)) |
Description: |
Array containing elements, one element per row, row number is elemID. |
The example mesh Fig. 2.1 with 4 elements is summarized in table Table 2.5. The example shows the four different elements (prism/hexahedron/tetrahedra/pyramid), the prism and hexa are in zone \(1\) and the tet and the pyramid in zone \(2\). A detailed list of the element type encoding is found in Section Element Types.
Element Type |
Zone |
offsetIndSIDE |
lastIndSIDE |
offsetIndNODE |
lastIndNODE |
|
---|---|---|---|---|---|---|
1 |
116 |
1 |
0 |
5 |
0 |
6 |
2 |
118 |
1 |
5 |
11 |
6 |
14 |
3 |
104 |
2 |
11 |
15 |
14 |
18 |
4 |
115 |
2 |
15 |
20 |
18 |
23 |
Element Type: |
Encoding for element type, see Section Element Types. |
Zone: |
Element group number. |
offsetIndSIDE/lastIndSIDE: |
Each element has a range of sides in the SideInfo array. |
offsetIndNODE/lastIndNODE: |
Each element has a range of node coordinates in the NodeCoords array and GlobalNodeIDs array for unique indices. |
The range and the size are always defined as: Range=[offset+1,last], Size=last-offset
2.3.3. FEM Element Information (FEMElemInfo)
This array will only exist if FEMConnect="ON"
(hopr parameterfile flag generateFEMconnectivity=T
).
Name in file: |
FEMElemInfo |
Type: |
INTEGER, Size: Array(1:4,1:nElems\(^*\)) |
Description: |
Array containing elements, one element per row, row number is elemID. |
The example mesh Fig. 2.1 with 4 elements is summarized in table Table 2.5. The example shows the four different elements (prism/hexahedron/tetrahedra/pyramid), the prism and hexa are in zone \(1\) and the tet and the pyramid in zone \(2\). A detailed list of the element type encoding is found in Section Element Types.
offsetIndEDGE |
lastIndEDGE |
offsetIndVERTEX |
lastIndVERTEX |
|
---|---|---|---|---|
1 |
0 |
9 |
0 |
6 |
2 |
9 |
21 |
6 |
14 |
3 |
21 |
27 |
14 |
18 |
4 |
27 |
35 |
18 |
23 |
offsetIndEDGE/lastIndEDGE: |
Each element has a range of edges in the EdgeInfo array. |
offsetIndVERTEX/lastIndVERTEX: |
Each element has a range of edges in the VertexInfo array. |
The range and the size are always defined as: Range=[offset+1,last], Size=last-offset
2.3.4. Side Information (SideInfo)
Name in file: |
SideInfo |
Type: |
INTEGER, Size: Array(1:6,1:nSides\(^*\)) |
Description: |
Side array, all information of one element is stored continuously (CGNS ordering, \rf{fig:CGNS}) |
in range ‘offsetIndSIDE+1:lastIndSIDE’ from ElemInfo. |
The SideInfo array for the example mesh Fig. 2.1 with 4 elements is given in table Table 2.11.
SideType |
GlobalSideID |
nbElemID |
10*nbLocSide+Flip |
BCID |
[#ElemID,locSideID] |
in ElemInfo |
|
---|---|---|---|---|---|---|---|
1 |
3 |
1 |
0 |
0 |
1 |
[#1,1] |
[(offsetIndSIDE,1)+1] |
2 |
14 |
2 |
2 |
43 |
0 |
[#1,2] |
|
3 |
14 |
3 |
0 |
0 |
3 |
[#1,3] |
|
4 |
14 |
4 |
0 |
0 |
4 |
[#1,4] |
|
5 |
3 |
5 |
3 |
12 |
0 |
[#1,5] |
[(lastIndSIDE,1)] |
6 |
14 |
6 |
0 |
0 |
1 |
[#2,1] |
[(offsetIndSIDE,2)+1] |
7 |
14 |
7 |
0 |
0 |
2 |
[#2,2] |
|
8 |
14 |
8 |
2 |
50 |
3 |
[#2,3] |
|
9 |
14 |
-2 |
1 |
23 |
0 |
[#2,4] |
|
10 |
14 |
9 |
2 |
30 |
4 |
[#2,5] |
|
11 |
14 |
10 |
4 |
14 |
0 |
[#2,6] |
[(lastIndSIDE,2)] |
12 |
3 |
-5 |
1 |
52 |
0 |
[#3,1] |
[(offsetIndSIDE,3)+1] |
13 |
3 |
11 |
4 |
42 |
0 |
[#3,2] |
|
14 |
3 |
12 |
0 |
0 |
3 |
[#3,3] |
|
15 |
3 |
13 |
0 |
0 |
4 |
[#3,4] |
[(lastIndSIDE,3)] |
16 |
14 |
-10 |
2 |
61 |
0 |
[#4,1] |
[(offsetIndSIDE,4)+1] |
17 |
3 |
15 |
0 |
0 |
2 |
[#4,2] |
|
18 |
3 |
16 |
0 |
0 |
3 |
[#4,3] |
|
19 |
3 |
-11 |
3 |
22 |
0 |
[#4,4] |
|
20 |
3 |
14 |
0 |
0 |
4 |
[#4,5] |
[(lastIndSIDE,4) ] |
SideType: |
Side type encoding, the number of corner nodes is the last digit (triangle/quadrangle), more details see Section Element Types. |
GlobalSideID: |
Unique global side identifier, can be directly used as MPI tag: it is negative if the side is a slave side (a master and a slave side is defined for side connections). |
nbElemID: |
ElemID of neighbor element (\(=0\) for no connection). This helps to quickly build up element connections, for local (inside local element range) as well as inter-processor element connections. |
10nbLocSide+Flip: |
first digit : local side of the connected neighbor element\(\in[1,\dots,6]\), last digit: Orientation between the sides (flip \(\in [0,\dots,4]\)), see Section Element Connectivity. |
BCID: |
Refers to the row index of the Boundary Condition List in BCNames/BCType array (\(\in[1,\dots\text{\texttt{nBCs}}]\)). \(=0\) for inner sides. Note that \(\neq 0\) for periodic and inner boundary conditions, while nbElemID and nbLocSide+Flip are given, see Section Boundary Conditions. |
2.3.5. Edge Information (EdgeInfo)
These arrays will only exist if FEMConnect="ON"
(hopr parameterfile flag generateFEMconnectivity=T
).
The EdgeInfo array includes the FEMEdgeID
of each local element edge in the same order as the CGNS edges as well as the offsetIndEDGEConnect
and the lastIndEDGEConnect
which refer to the corresponding position on the additional EdgeConnectInfo
array. Here, the nbElemID
as well as the localEdgeID
in the corresponding nbElemID
are saved.
Therefore, the multiplicity is given as multiplicity=lastEdgeConnect - offSetEdgeConnect+1
.
Name in file: |
EdgeInfo |
Type: |
INTEGER, Size: Array(1:3,1:nEdges\(^*\)) |
Description: |
Edge array, all information of one element is stored continuously (CGNS ordering, \rf{fig:CGNS}) |
in the range ‘offsetIndEDGE+1:lastIndEDGE’ from FEMElemInfo. |
The EdgeInfo array for the example mesh Fig. 2.2 with 4 elements is given in table Table 2.14.
(+/- orientation)FEMEdgeID |
offsetIndEDGEConnect |
LastIndEDGEConnect |
[#ElemID,locEdgeID] |
[in FEMElemInfo] |
|
---|---|---|---|---|---|
1 |
- 6 |
0 |
1 |
[#1,1] |
[(offsetIndEDGE,1)+1] |
2 |
- 10 |
1 |
2 |
[#1,2] |
|
3 |
+ 2 |
2 |
2 |
[#1,3] |
|
4 |
+ 11 |
2 |
3 |
[#1,4] |
[(lastIndEDGE,1)] |
5 |
+ 7 |
3 |
3 |
[#2,1] |
[(offsetIndEDGE,2)+1] |
6 |
- 8 |
3 |
4 |
[#2,2] |
|
7 |
+ 6 |
4 |
5 |
[#2,3] |
|
8 |
- 9 |
5 |
6 |
[#2,4] |
[(lastIndEDGE,2)] |
9 |
+ 3 |
6 |
6 |
[#3,1] |
[(offsetIndEDGE,3)+1] |
10 |
+ 10 |
6 |
7 |
[#3,2] |
|
11 |
+ 8 |
7 |
8 |
[#3,3] |
|
12 |
- 5 |
8 |
9 |
[#3,4] |
[(lastIndEDGE,3)] |
13 |
+ 1 |
9 |
9 |
[#4,1] |
[(offsetIndEDGE,4)+1] |
14 |
+ 5 |
9 |
10 |
[#4,2] |
|
15 |
+ 9 |
10 |
11 |
[#4,3] |
|
16 |
- 11 |
11 |
12 |
[#4,4] |
[(lastIndEDGE,4)] |
FEMEdgeID: |
Topologically unique global edge ID, includes periodicity. Sign refers to the local to global edge orientation ( |
offsetIndEDGEConnect/lastIndEDGEConnect: |
Each local element edge has a range of neighbor element edges in the EdgeConnectInfo array |
(+/- master/slave) nbElemID |
(+/- orientation)nbLocEdgeID |
[#ElemID,locEdgeID,FEMEdgeID] |
[in EdgeInfo] |
|
---|---|---|---|---|
1 |
+ 2 |
+ 3 |
[#1,1,6 ] |
[(offsetIndEDGEConnect, 1)+1] |
2 |
- 3 |
+ 2 |
[#1,2,10] |
[(offsetIndEDGEConnect, 2)+1] |
3 |
+ 4 |
- 4 |
[#1,4,11] |
[(offsetIndEDGEConnect, 4)+1] |
4 |
- 3 |
+ 3 |
[#2,2,8 ] |
[(offsetIndEDGEConnect, 6)+1] |
5 |
- 1 |
- 1 |
[#2,3,6 ] |
[(offsetIndEDGEConnect, 7)+1] |
6 |
- 4 |
+ 3 |
[#2,4,9 ] |
[(offsetIndEDGEConnect, 8)+1] |
7 |
+ 1 |
- 2 |
[#3,2,10] |
[(offsetIndEDGEConnect,10)+1] |
8 |
+ 2 |
- 2 |
[#3,3,8 ] |
[(offsetIndEDGEConnect,11)+1] |
9 |
- 4 |
+ 2 |
[#3,4,5 ] |
[(offsetIndEDGEConnect,12)+1] |
10 |
+ 3 |
- 4 |
[#4,2,5 ] |
[(offsetIndEDGEConnect,14)+1] |
11 |
+ 2 |
- 4 |
[#4,3,9 ] |
[(offsetIndEDGEConnect,15)+1] |
12 |
- 1 |
+ 4 |
[#4,4,11] |
[(offsetIndEDGEConnect,16)+1] |
nbElemID: |
element ID of connected element via the edge. Sign refers if the neighbor edge is master or slave ( |
from the master slave information, the master/slave of the elements’ edge can be deduced |
|
nbLocEdgeID: |
local Edge ID in neighbor element. Sign refers to the local to global edge orientation of neighbor edge ( |
2.3.6. Vertex Information (VertexInfo)
These arrays will only exist if FEMConnect="ON"
(hopr parameterfile flag generateFEMconnectivity=T
).
The VertexInfo array includes the FEMVertexID
of each local element vertex in the same order as the CGNS corners as well as the offsetIndVERTEXConnect
and the lastIndVERTEXConnect
which refer to the corresponding position in the additional VertexConnectInfo array. Here, the nbElemID
as well as the localNodeID
in the corresponding nbElemID
are saved.
Therefore, the multiplicity is given as multiplicity = lastIndVERTEXConnect- offsetIndVERTEXConnect + 1.
{table} Vertex Information
---
name: tab:vertex_info
---
| | |
| :--- | :--- |
| Name in file: | **VertexInfo** |
| Type: | INTEGER, Size: Array(1:3,1:**nVertices**$^*$) |
| Description: | Vertex array, all information of one element is a stored continuously (CGNS ordering, \rf{fig:CGNS}) |
| | in the range 'offsetIndVERTEX+1:lastIndVERTEX' from **FEMElemInfo**. |
FEMVertexID |
offsetIndVERTEXConnect |
lastIndVERTEXConnect |
[#ElemID,locVertexID] |
[ in FEMElemInfo ] |
|
---|---|---|---|---|---|
1 |
5 |
0 |
2 |
[#1,1] |
[(offsetIndVERTEX,1)+1 ] |
2 |
6 |
2 |
4 |
[#1,2] |
|
3 |
3 |
4 |
5 |
[#1,3] |
|
4 |
4 |
5 |
6 |
[#1,4] |
[ (lastIndVERTEX,1) ] |
5 |
2 |
6 |
9 |
[#2,1] |
[(offsetIndVERTEX,2)+1 ] |
6 |
2 |
9 |
12 |
[#2,2] |
|
7 |
6 |
12 |
14 |
[#2,3] |
|
8 |
5 |
14 |
16 |
[#2,4] |
[ (lastIndVERTEX,2) ] |
9 |
1 |
16 |
17 |
[#3,1] |
[(offsetIndVERTEX,3)+1 ] |
10 |
3 |
17 |
18 |
[#3,2] |
|
11 |
6 |
18 |
20 |
[#3,3] |
|
12 |
2 |
20 |
23 |
[#3,4] |
[ (lastIndVERTEX,3) ] |
13 |
4 |
23 |
24 |
[#4,1] |
[(offsetIndVERTEX,4)+1 ] |
14 |
1 |
24 |
25 |
[#4,2] |
|
15 |
2 |
25 |
28 |
[#4,3] |
|
16 |
5 |
28 |
30 |
[#4,4] |
[ (lastIndVERTEX,4) ] |
FEMVertexID: |
Topologically unique global vertex ID, includes periodicity (needed for a FEM solver) |
offsetIndVERTEXConnect/lastIndVERTEXConnect: |
Each local element vertex has a range of neighbor element edgvertices in the VertexConnectInfo array. |
Name in file: |
VertexConnectInfo |
Type: |
INTEGER, Size: Array(1:2,1:nFEMVertexConnections) |
Description: |
Array of connected vertices, all information of one vertex is stored continuously |
in the range |
(+/- master/slave) nbElemID |
localNodeID |
[#ElemID,locVertexID,FEMVertexID] |
[in VertexInfo] |
|
---|---|---|---|---|
1 |
- 4 |
4 |
[#1,1,5] |
[(offsetIndVERTEXConnect,1)+1] |
2 |
- 2 |
4 |
[#1,1,5] |
[ (lastIndVERTEXConnect,1) ] |
3 |
- 2 |
3 |
[#1,2,6] |
[(offsetIndVERTEXConnect,2)+1] |
4 |
- 3 |
3 |
[#1,2,6] |
[ (lastIndVERTEXConnect,2) ] |
5 |
- 3 |
2 |
[#1,3,3] |
[(offsetIndVERTEXConnect,3)+1] |
6 |
- 4 |
1 |
[#1,4,4] |
[(offsetIndVERTEXConnect,4)+1] |
7 |
- 4 |
3 |
[#2,1,2] |
[(offsetIndVERTEXConnect,5)+1] |
8 |
- 3 |
4 |
[#2,1,2] |
|
9 |
- 2 |
2 |
[#2,1,2] |
[ (lastIndVERTEXConnect,5) ] |
10 |
- 4 |
3 |
[#2,2,2] |
[(offsetIndVERTEXConnect,6)+1] |
11 |
- 3 |
4 |
[#2,2,2] |
|
12 |
+ 2 |
1 |
[#2,2,2] |
[ (lastIndVERTEXConnect,6) ] |
13 |
+ 1 |
2 |
[#2,3,6] |
[ (offsetIndVERTEXConnect,7)+1] |
14 |
- 3 |
3 |
[#2,3,6] |
[ (lastIndVERTEXConnect,7) ] |
15 |
+ 1 |
1 |
[#2,4,5] |
[ (offsetIndVERTEXConnect,8)+1] |
16 |
- 4 |
4 |
[#2,4,5] |
[ (lastIndVERTEXConnect,8) ] |
17 |
+ 4 |
2 |
[#3,1,1] |
[ (offsetIndVERTEXConnect,9)+1] |
18 |
+ 1 |
3 |
[#3,2,3] |
[(offsetIndVERTEXConnect,10)+1] |
19 |
+ 1 |
2 |
[#3,3,6] |
[(offsetIndVERTEXConnect,11)+1] |
20 |
- 2 |
3 |
[#3,3,6] |
[ (lastIndVERTEXConnect,11) ] |
21 |
- 2 |
2 |
[#3,4,2] |
[(offsetIndVERTEXConnect,12)+1] |
22 |
+ 2 |
1 |
[#3,4,2] |
|
23 |
- 4 |
3 |
[#3,4,2] |
[ (lastIndVERTEXConnect,12) ] |
24 |
+ 1 |
4 |
[#4,1,4] |
[(offsetIndVERTEXConnect,13)+1] |
25 |
- 3 |
1 |
[#4,2,1] |
[(offsetIndVERTEXConnect,14)+1] |
26 |
+ 2 |
1 |
[#4,3,2] |
[(offsetIndVERTEXConnect,15)+1] |
27 |
- 2 |
2 |
[#4,3,2] |
|
28 |
- 3 |
4 |
[#4,3,2] |
[ (lastIndVERTEXConnect,15) ] |
29 |
+ 1 |
1 |
[#4,4,5] |
[(offsetIndVERTEXConnect,16)+1] |
30 |
- 2 |
4 |
[#4,4,5] |
[ (lastIndVERTEXConnect,16) ] |
nbElemID: |
element ID of connected element via the vertex. Sign refers if the neighbor vertex is master or slave ( |
from the master slave information, the master/slave of the elements’ vertex can be deduced |
|
nbLocVertexID: |
local vertex ID in neighbor element. |
2.3.7. Node Coordinates and Global Index
Name in file: |
NodeCoords |
Type: |
REAL \quad Size: Array(1:3,1:nNodes\(^*\)) |
Description: |
The coordinates of the nodes of the element, as a set for each element. |
offsetIndNODE/lastIndNODE in ElemInfo refers to the row index of one set of element nodes. |
Name in file: |
GlobalNodeIDs |
Type: |
INTEGER \quad Size: Array(1:nNodes\(^*\)) |
Description: |
The unique global node identifier corresponding to the node at the same array position in NodeCoords. |
The node list contains the high order nodes of the element, so the number of nodes per element depends on the polynomial degree of the element mapping \(N_{geo}\). From this list, the corner nodes can be extracted. The details of the node ordering are explained in Section Element High Order Nodes. It is important to note that in the case of \(N_{geo}=1\), our node ordering does NOT correspond to the CGNS corner node ordering for pyramids and hexahedra. Note that the nodes are multiply stored because of the parallel I/O, and therefore the GlobalNodeID is needed for a unique node indexing.
The NodeCoordsand GlobalNodeIDs array for the example mesh Fig. 2.1 with 4 elements is given in table Table 2.25. The node ordering is explained in Section Element High Order Nodes.
NodeCoords |
GlobalNodeIDs |
in ElemInfo |
|
---|---|---|---|
\((x,y,z)_{ 5}\) |
5 |
(offsetIndNODE,1)+1 |
|
\((x,y,z)_{ 3}\) |
3 |
||
\((x,y,z)_{ 4}\) |
4 |
||
\((x,y,z)_{11}\) |
11 |
||
\((x,y,z)_{ 9}\) |
9 |
||
\((x,y,z)_{ 6}\) |
6 |
(lastIndNODE,1) |
|
\((x,y,z)_{ 1}\) |
1 |
(offsetIndNODE,2)+1 |
|
\((x,y,z)_{ 2}\) |
2 |
||
\((x,y,z)_{ 5}\) |
5 |
||
\((x,y,z)_{ 3}\) |
3 |
||
\((x,y,z)_{ 7}\) |
7 |
||
\((x,y,z)_{ 8}\) |
8 |
||
\((x,y,z)_{11}\) |
11 |
||
\((x,y,z)_{ 9}\) |
9 |
(lastIndNODE,2) |
|
\((x,y,z)_{11}\) |
11 |
(offsetIndNODE,3)+1 |
|
\((x,y,z)_{ 9}\) |
9 |
||
\((x,y,z)_{ 6}\) |
6 |
||
\((x,y,z)_{10}\) |
10 |
(lastIndNODE,3) |
|
\((x,y,z)_{ 7}\) |
7 |
(offsetIndNODE,4)+1 |
|
\((x,y,z)_{ 8}\) |
8 |
||
\((x,y,z)_{11}\) |
11 |
||
\((x,y,z)_{ 9}\) |
9 |
||
\((x,y,z)_{10}\) |
10 |
(lastIndNODE,4) |
2.3.8. Boundary Conditions
Name in file: |
BCNames |
Type: |
STRING, \quad Size: Array(1:nBCs) |
Description: |
User-defined list of boundary condition names. |
Name in file: |
BCType |
Type: |
INTEGER, \quad Size: Array(1:4,1:nBCs) |
Description: |
User-defined array of 4 integers per boundary condition. |
The boundary conditions are completely defined by the user. Each BCID from the SideInfo array refers to the position of the boundary condition in the BCNames list. An additional 4 integer code in BCType is available for user-defined attributes.
Ind |
Boundary Conditions Name: |
BCType |
|
---|---|---|---|
1 |
lowerWall |
(4,0,0,0) |
|
2 |
Inflow |
(2,0,0,0) |
|
3 |
OutflowRight |
(10,0,0,0) |
|
4 |
OutflowLeft |
(8,0,0,0) |
The BCType array consists of the following entries, of which some are specific to HOPR:
BoundaryType: |
Actual type of boundary condition (e.g. inflow, outflow, periodic). {Reserved values:} BoundaryType=1 is reserved for periodic boundaries and BoundaryType=100 is reserved for “inner” boundaries or “analyze sides”. For these two cases the sides in the SideInfo array will have a neighbor side/element/flip specified, all other sides with BCs are not connected! |
CurveIndex: |
Geometry tag used to distinguish between multiple BCs of the same type, e.g. to specify the original CAD surface belonging to the mesh side. Also used to control some mesh curving features, sides with CurveIndex\(>\)0 are curved, while sides with CurveIndex=0 are mostly (bi-) linear. |
StateIndex: |
Specifies the index of a reference state to be used inside the solver. This value is completely used-defined and will not be used/checked/modified by HOPR. |
PeriodicIndex: |
Only relevant for periodic sides, ignored for others. For periodic connections two boundary conditions are required, having the same absolute PeriodicIndex, one with positive, the other with negative sign. |
2.4. Parallel Read-in
The overall parallel read-in process is depicted in Fig. 2.3. The Algorithms Fig. 2.4, Fig. 2.5, Fig. 2.6 describe how to open and close a HDF5 file and read the file attributes.
Each parallel process (MPI rank) has to read a contiguous element range, which will be basically defined by dividing the total number of elements by the number of domains, already leading to the domain decomposition. The element distribution is computed locally on each rank. Follow Fig. 2.7 for an equal distribution of an arbitrary number of elements on an arbitrary number of domains/ranks. The algorithm is easy to extend to account for different element weights. The element distribution is saved in the offsetElem array of size 0:nDomains. The element range for each domain (mydom\(\in\)[0:nDomains-1]) is then
ElementRange(myDom)=[offsetElem(myDom)+1;offsetElem(myDom+1)]
Note that the offsetElem array will have the information of all element ranges of all ranks, which is very helpful for building the inter-domain mesh connectivity to quickly find neighbor elements on other domains/ranks.
Using the number of local elements and the offset, we read the non-overlapping sub-arrays of the ElemInfo array in parallel (using hyperslab HDF5 commands, see Fig. 2.8), which will assign a continuous sub-array of element informations for each rank. With the local element informations, we easily compute the offset and size of sub-arrays for the side data (SideInfo) and node data (NodeCoords), by computing
firstElem = |
offsetElem(myDom)+1 |
lastElem = |
offsetElem(myDom+1) |
firstSide = |
ElemInfo (offsetIndSIDE,firstElem)+1 |
lastSide = |
ElemInfo (lastIndSIDE,lastElem) |
firstNode = |
ElemInfo (offsetIndNODE,firstElem)+1 |
lastNode = |
ElemInfo (lastIndNODE,lastElem) |
and again read the non-overlapping sub-arrays in parallel. Now element geometry is easily built locally. Local element connectivities would only have neighbor element indices inside the local element range and can directly be assigned. The overall read-in process is summarized in Fig. 2.9.
For the inter-domain connectivity, we have to find the domain containing the neighbor element. A quick search is done with a bisection of the offsetElem array, since element ranges are monotonically increasing, see Fig. 2.10.
Finally, we group the sides connected to each neighbor domain and sort the sides along the global side index (known from SideInfo). This creates the same side list on both domains without any communication. If an orientation of the side link is needed, the side is always marked either master or slave (positive or negative global side index).
2.5. Element Definitions
2.5.1. Element Types
The classification of the element types is given in Table 2.30. The last digit is always the number of corner nodes. The classification is geometrically motivated. The element has a linear mapping if \(N_{geo}=1\) and the corner nodes are an affine transformation of the reference element corner nodes, whereas bilinear stands for the general straight-edged element with \(N_{geo}=1\), and non-linear for the high order case \(N_{geo} \ge 1\).
For mesh file read-in, only the number of element corner nodes is important to distinguish the 3D elements, since the polynomial degree \(N_{geo}\) is globally defined.
ElementType |
Index |
ElementType |
Index |
ElementType |
Index |
---|---|---|---|---|---|
Triangle, linear |
3 |
Tetrahedron, linear |
104 |
Prism, bilinear |
116 |
Quad, linear |
4 |
Pyramid, linear |
105 |
Hexahedron, bilinear |
118 |
Prism, linear |
106 |
Tetrahedron, non-linear |
204 |
||
Quad, bilinear |
14 |
Hexahedron, linear |
108 |
Pyramid, non-linear |
205 |
Triangle, non-linear |
23 |
Prism, non-linear |
206 |
||
Quad, non-linear |
24 |
Pyramid, bilinear |
115 |
Hexahedron, non-linear |
208 |
2.5.2. Element High Order Nodes
In the arrays NodeCoords and GlobalNodeIDs (Section Node Coordinates and Global Index), the element high order nodes are found as a node list, \(1,\dots,\ell,\dots M_\text{elem}\). The number of nodes for each element is defined by the element type and the polynomial degree \(N_{geo}\) of the mapping and is listed in Table 2.31. See Section Element Corners, Sides if one needs only the corner nodes of the linear mesh.
Element Type: |
#Corner nodes |
#HO nodes (\(M_\text{elem}\)) |
---|---|---|
Triangle |
3 |
\(\frac{1}{2}(N_{geo}+1)(N_{geo}+2)\) |
Quad |
4 |
\((N_{geo}+1)^2\) |
Tetrahedron |
4 |
\(\frac{1}{6}(N_{geo}+1)(N_{geo}+2)(N_{geo}+3)\) |
Pyramid |
5 |
\(\frac{1}{6}(N_{geo}+1)(N_{geo}+2)(2N_{geo}+3)\) |
Prism |
6 |
\(\frac{1}{2}(N_{geo}+1)^2( N_{geo}+2)\) |
Hexhedron |
8 |
\((N_{geo}+1)^3\) |
The mapping from the node list to the node position
is defined by Fig. 2.12 and an example is shown for quadratic mapping in Fig. 2.11. The high order node positions are regular in reference space \(-1\leq (\xi,\eta,\zeta) \leq 1 \) and therefore can be easily computed from the \((i,j,k)\) index of the node \(\ell\) by
2.5.3. Element Corners, Sides
To define the element corner nodes, the side order and side connectivity, we follow the standard from CGNS SIDS (CFD General Notation System, Standard Interface Data Structures, [http://cgns.sourceforge.net/][http://cgns.sourceforge.net/] ). The definition is sketched in Fig. 2.13. To get the CGNS corner nodes from the high order node list, follow Fig. 2.14. Note that in the case of \(N_{geo}=1\), the node ordering does not correspond to the CGNS corner node ordering for pyramids and hexahedra!
Especially, the CGNS standard defines a local coordinate system of each element side. The side’s first node will be the origin, and the remaining nodes are ordered in the direction of the outward pointing normal.
2.5.4. Element Connectivity
In the SideInfo array, we explicitly store the side-to-side connectivity information between elements, consisting of the neighbor element ID, the local side of the neighbor and the orientation, encoded with the variable flip. Using the local side system, the orientation between elements boils down to three cases for a triangular element side and four for a quadrilateral element side. The definition is given in Fig. 2.15. Also note that the flip in Table 2.32 is symmetric, having the same value if seen from the neighbor side.
flip\(=1\): |
\(1^{st}\) |
node of neighbor side = \(1^{st}\) node of side |
flip\(=2\): |
\(2^{nd}\) |
node of neighbor side = \(1^{st}\) node of side |
flip\(=3\): |
\(3^{rd}\) |
node of neighbor side = \(1^{st}\) node of side |
flip\(=4\): |
\(4^{th}\) |
node of neighbor side = \(1^{st}\) node of side |
2.6. Additional Extensions: Hanging Node Interface
For complex geometries it is often desirable to use elements with hanging nodes to provide more geometric flexibility when meshing. As geometric restrictions are most severe for pure hexahedral meshes, the HOPR format supports a limited octree-like topology with hanging nodes for purely hexahedral meshes. The octree topology is implemented as extension to the existing mesh structure. While full octrees permit an element-side to have an arbitrary number of neighbors on various octree levels, our format supports only one octree level difference between element sides with two (anisotropic) and four neighbors, the single types are depicted in Fig. 2.16.
For the connection of two elements over an octree level additional interfaces are required, which are termed mortar interfaces and are depicted in Fig. 2.17. Thereby the big side is denoted big mortar master side, the intermediate sides are denoted small mortar master sides. The sides of the small elements are denoted slave sides. Note that they do not require any information about the mortar interface and therefore the interface is only represented from the big element side in the data format.
The following differences are present for the ElemInfo and the SideInfo array:
2.6.1. Changes to Existing Data Format
ElemInfo: The range of sides defined by offsetIndSIDE and lastIndSIDE now includes the small mortar master sides for the element that owns the big mortar side.
SideInfo: The field nbElemID of the big mortar side defines no connection to the neighbor element, but contains the type of the mortar interface (=1/2/3) from Fig. 2.16 with negative sign, to mark that the following sides belong to a mortar interface. The type of the interface defines the number of the small mortar master sides (Type 1 has 4 and Type 2&3 have 2 small master sides).
SideInfo: The list of sides belonging to an element includes the small mortar master sides sorted as exemplified in Table 2.33 and Fig. 2.17.
SideInfo: Only the small mortar masters have a valid nbElemID, defining the connection to the adjacent small elements.
SideInfo: (Mortar) Master sides always have flip=0, thus the small element sides are always slave sides.
SideInfo: If the element side belongs to a mortar but with the small mortar slave side, it is marked as such using a SideType with negative sign.
Global SideID |
local SideID |
local MortarID |
---|---|---|
42 |
1 |
0 |
43 |
1 |
1 |
44 |
1 |
2 |
45 |
1 |
3 |
46 |
1 |
4 |
47 |
2 |
0 |
48 |
3 |
0 |
49 |
3 |
1 |
50 |
3 |
2 |
51 |
4 |
0 |
52 |
5 |
0 |
53 |
6 |
0 |
2.6.2. Additional Information for Octrees
In addition to the existing format defined above, the mortar format contains non-necessary additional information concerning the octrees. It contains the octree node coordinates and a mapping of the element to the octrees. Note that the polynomial degree of the element mapping is defined as \(N_{geo}\), while the octrees may have an independent polynomial degree \(N_{g,tree}\). Elements and trees can be identical in case the element is on the lowest octree level and the polynomial degrees are identical.
2.6.2.1. Octree Global Attributes
In addition to the global attributes defined in Section Global Attributes, the non-conforming mesh format includes the following attributes.
Attribute |
Data type |
Description |
---|---|---|
IsMortarMesh |
INTEGER |
Identify mesh as a mortar mesh, if present |
NgeoTree \(\geq 1\) |
INTEGER |
Polynomial degree \(N_{g,tree}\) of tree mapping, used to determine the number of nodes per element |
nTrees |
INTEGER |
Total number of octrees |
nNodesTree |
INTEGER |
Total number of tree nodes: \((N_{g,tree}+1)^3 \cdot nTrees\) |
2.6.2.2. Mapping of the Global Element Index (ElemID) to the Octree Index (TreeID)
Name in file: |
ElemToTree |
Type: |
INTEGER \(\quad\) Size: Array(1:nElems\(^*\)) |
Description: |
The mapping from the global element index (ElemID) to its corresponding octree index (TreeID) if applicable. |
2.6.2.3. Element Bounds in Tree Reference Space
Name in file: |
xiMinMax |
Type: |
REAL \(\quad\) Size: Array(1:3,1:2,1:nElems\(^*\)) |
Description: |
The array contains the element bounds in the tree reference space \([-1,1]^3\) given by the minimum (1:3,1,ElemID) and maximum (1:3,2,ElemID) corner nodes. |
2.6.2.4. Node Coordinates of the Octrees
Name in file: |
TreeCoords |
Type: |
REAL \(\quad\) Size: Array(1:3,nNodesTree\(^*\)) |
Description: |
The coordinates of the nodes of the tree, as a set for each tree. |