In this second post of a four-part series you will read the details about how to use the new import API in the Pointwise Plugin SDK to write an importer for unstructured grid data.
Yes, you read that correctly. You can now create grid import plugins for Pointwise! If Pointwise does not yet import the grid format you use, you no longer need to wait for Pointwise to add it for you. You can easily add it yourself. For an introduction, see Part 1 of this series.
The Pointwise Plugin SDK now includes a new Grid Import Plugin API which provides a mechanism by which structured and unstructured grid data can be read from an external source and then converted into a representation that is understood by Pointwise. At this time, only the import of raw grid data is supported. That is, the import of boundary conditions and volume conditions is not yet supported. The addition of BC and VC support in future releases will be guided by user feedback.
To properly import grid data, you need a thorough understanding of the Pointwise Grid Model API. In this post, I will focus on the import of unstructured grid data. The import of structured grid data will be covered in part 3 of this series.
Through out the code examples in this post, you will see the use of Pointwise Grid Model API data types called handles.
Handles are used to uniquely identify a Pointwise Grid Model entity or element without using pointers. For those of you familiar with C++, a handle can be considered the Pointwise Grid Model’s equivalent of a C++ this pointer. The Pointwise Grid Model API supports six handle types for use with unstructured grids:
Each handle type has one or more Pointwise Grid Model API functions that are used to query or manipulate the entity that the handle represents.
The Pointwise Grid Model API uses a function naming scheme in which the name’s prefix reflects the entity handle being accessed. For example, all functions beginning with
PwDom take a
PWGM_HDOMAIN as their first parameter (the domain’s this pointer).
You can also extract meta information from a handle using various Pointwise Grid Model API macros. For more details, see the The Pointwise Grid Model API / Using C / Data Types / PWGM-API Opaque Data handle Types section on the Pointwise Plugin SDK Modules page.
The imported grid data is created in a hierarchy. The root of this hierarchy is accessed via a PWGM_HGRIDMODEL handle. At import, the PWGM_HGRIDMODEL is passed to the plugin’s entry point function
runtimeReadGrid(GRDP_RTITEM *pRti) via the
pRti->model data member.
There is a slight difference in the process used to create structured grid entities versus unstructured grid entities. This difference is motivated by the inverted relationship between a structured and unstructured grid entity and its vertices as shown in the diagram.Unstructured grid entities depend on a shared, linear array of N vertices indexed in the range [0, N-1].
Unstructured Grid Files 101
There are two basic types of unstructured grid file formats, cell-based and face-based.
A cell-based format defines a grid as a collection of cell elements. A 3D, cell-based grid defines volume cell types such as tetrahedrons or pyramids. A 2D, cell-based grid defines triangle and quadrangle cell types.
A face-based format defines a grid as a collection of faces tagged with the id of the cells on either side of the face. A 3D, face-based grid defines triangle and quadrangle face types. A 2D, face-based grid defines bar (line) face types.
A typical unstructured grid file format has three common elements:
- A single array of N, shared vertices
- One or more lists of unstructured grid cell elements or cell faces
- One or more lists of unstructured grid boundary elements
Depending on the dimensionality (2D or 3D) of a grid, a grid file’s vertices may be defined by two or three floating point coordinate values. The values may be stored in the file with single or double precision. In a 3D grid file, each vertex must be defined by an XYZ coordinate triple. However, 2D grid files may define each vertex with either an XYZ triple, or an XY, YZ, or XZ coordinate pair. The Pointwise Grid Model API expects vertices defined as double precision, XYZ coordinate triples.
An unstructured grid element’s connectivity (and resulting physical shape) is defined by a list of integer values. These integer values are linear indices into the shared vertex array. By sharing the vertex array, neighboring elements will have common indices at their interfaces (i.e. the blue edge labeled 2 in diagram below).
Some grid file formats use 1-based vertex array indices in the range [1, N]. Other formats will use 0-based vertex array indices in the range [0, N-1]. The Pointwise Grid Model API always expects 0-based indices when adding element definitions to the grid model. A simple, 2D unstructured grid with both its cell-based and face-based representations is given in the following diagram.
The Pointwise Grid Model API supports the canonical 2D elements Triangle, and Quadrangle, along with the canonical 3D elements Tetrahedron, Pyramid, Wedge (a.k.a Prism), and Hexahedron. General element types are not supported at this time. The ordering of an element’s indices is specified by each grid file format. Imported grid elements must have their indices reordered to match the index order required by the Pointwise Grid Model API as defined in the following diagram.
Creating an Unstructured Vertex List
At least one unstructured vertex list is needed when creating an unstructured grid. A typical unstructured grid file will only contain a single vertex list that is shared by all of its grid entities. However, some formats such as VRML may define multiple vertex lists. Creating multiple vertex lists during an import is supported. However, it is the import plugin’s responsibility to use the proper vertex list when creating grid entities.
A vertex list is created using the three steps listed below. The relevant API calls are listed below each step. If multiple API calls are available, use the calls that are most convenient for your plugin’s implementation.
- Create a vertex list
- Preallocate XYZ storage for the vertex list
PwVlstAllocate(PWGM_HVERTEXLIST vertlist, const PWP_UINT n)
- Load the vertex coordinate values into the vertex list
PwVlstSetXYZVal(PWGM_HVERTEXLIST vertlist, PWP_UINT ndx, PWGM_ENUM_XYZ which, PWGM_XYZVAL val)
PwVlstSetXYZ(PWGM_HVERTEXLIST vertlist, PWP_UINT ndx, PWGM_XYZVAL x, PWGM_XYZVAL y, PWGM_XYZVAL z)
PwVlstSetXYZData(PWGM_HVERTEXLIST vertlist, PWP_UINT ndx, PWGM_VERTDATA &v)
Creating a Cell-based Unstructured Mesh
Use this approach if a grid file defines mesh elements as cells.
- Create one or more unstructured grid entities that reference the vertex list
- Allocate memory for the grid entity (optional, recommended)
PwUnsBlkAllocateElements(PWGM_HBLOCK block, PWGM_ENUM_ELEMTYPE cellType, PWP_UINT count)
PwUnsBlkAllocateElementCounts(PWGM_HBLOCK block, PWGM_ELEMCOUNTS &counts)
PwUnsDomAllocateElements(PWGM_HDOMAIN domain, PWGM_ENUM_ELEMTYPE cellType, PWP_UINT n)
PwUnsDomAllocateElementCounts(PWGM_HDOMAIN domain, PWGM_ELEMCOUNTS &counts)
- Load element connectivity into the grid entity
PwUnsBlkSetElement(PWGM_HBLOCK block, PWP_UINT ndx, PWGM_ELEMDATA *eData)
PwUnsDomSetElement(PWGM_HDOMAIN domain, PWP_UINT ndx, PWGM_ELEMDATA *eData)
The allocation step listed above is not strictly required. However, it is a best practice to do so if the cell-type counts are easily obtained.
Creating a Face-based Unstructured Mesh
Use this approach if a grid file defines mesh elements in terms of its cell faces.
- Create a block assembler
- Load element faces into the assembler
PwAsmPushElementFace(PWGM_HBLOCKASSEMBLER blkAsm, PWGM_ASSEMBLER_DATA *face)
- Complete the block
The call to
PwAsmFinalize() will stitch together the faces pushed into the assembler and form closed, watertight mesh elements.
Armed with an understanding of the Pointwise Grid Model API for importing unstructured grid data, you should be able to create a plugin that adds your grid importer of choice to Pointwise. Visit the Pointwise Plugin SDK section of our website to get started.
In Part 3 of this 4-part series, you will read about writing an importer for structured grids.