Read and Print Model Data

This example illustrates loading a Model object with typically a finite element model residing on an external file and then traversing and printing the node coordinates and element connectivity contained in the Connect object registered in the Model object. The finite element model may reside on any external file in a format supported by VdmTools. The external file name is entered as the first argument to the example executable. If no file name is entered then the file “bumper.unv”, a simple IDEAS universal file, is assumed.

Overview

The example performs the following main tasks:

  1. Parse command line arguments, set input file and validate license
  2. Open the file using Library Manager, check for errors and handle them appropriately
  3. Load the model and check for errors
  4. Get the connect object and check for errors
  5. Print the list of nodes with their coordinates and their associated coordinate system, if any
  6. Print the connectivity of the mesh
  7. Clean up resources

Let’s examine each step in detail.

Step 1: Initialize and Setup

First, we include necessary headers, declare variables, and handle command line arguments:

C
#include "sam/base/base.h"
#include "sam/vdm/vdm.h"
#include "sam/base/license.h"
#include "sam/vdm/datafile.h"
#include "sam/hoops_license.h"

int main(int argc, char** argv)
{
    char inputFile[256];
    Vint fileType;

    /* check input arguments */
    if (argc < 2) {
        fprintf(stderr, "Usage: %s inputfile [appendfile]\n", argv[0]);
        fprintf(stderr, " inputfile is blank, 'bumper.unv' is assumed\n");
        strcpy(inputFile, "bumper.unv");
    }
    else {
        strcpy(inputFile, argv[1]);
    }

    vsy_LicenseValidate(HOOPS_LICENSE);

The program provides helpful information about the mesh in the “bumper.unv” file which is provided along with the SDK.

Step 2: Open File with Library Manager and check for errors

Next, we create a Library Manager and open the input file:

C
/* Open file */
vdm_LMan* libraryManager = vdm_LManBegin();
vdm_LManOpenFile(libraryManager, inputFile, nullptr);

/* check for error */
Vint ierr = vdm_LManError(libraryManager);
if (ierr) {
    fprintf(stderr, "Error: opening file %s\n", inputFile);
    vdm_LManCloseFile(libraryManager);
    vdm_LManEnd(libraryManager);
    exit(1);
}

The LMan (Library Manager) provides a high-level interface for file operations, automatically detecting the file format and initializing the appropriate library based on the file format. A nullptr is provided instead of options since we are not interested in any particular options or conventions while reading this file. Proper error checking is essential when working with file operations. The Library Manager provides a simple error checking mechanism through vdm_LManError.

Step 3: Load the model and check for errors

Now we instance the model and the library manager is asked to read the finite element model informations and inject it into the model object:

C
/* instance model object for finite element model */
vis_Model* model = vis_ModelBegin();

/* use Library Manager object to load model */
vdm_LManLoadModel(libraryManager, model);
if (vdm_LManError(libraryManager)) {
    fprintf(stderr, "Error: Unable to load model information\n");
    exit(1);
}

The Library Manager provides through vdm_LManLoadModel function, a simple way to obtain all the model data contained in the file. It provides also a simple error checking mechanism through vdm_LManError. The Model (Finite Element Model) encapsulates all objects which define an entire finite element model. This includes the mesh, but also all boundary conditions, initial conditions, materials, global control parameters, etc.

Step 4: Get the connect object and check for errors

Now we get the connect attribute object from the model:

C
 /* get Connect object and print nodes and elements */
 vis_Connect* connect = NULL;
 vis_ModelGetObject(model, VIS_CONNECT, (Vobject**)&connect);
 if (connect != NULL) {
     printNodes(connect);
     printElements(connect);
}

The Connect (Finite Element Grids) manages all data related to the finite element mesh: the coordinates, the connectivities, but also the adjacency properties. The vis_ModelGetObject function gets pointer to the object type defined by the parameter VIS_CONNECT parameter, which in this case is the Connect object. It returns a NULL pointer if if the connect object could not be extracted from the model.

Step 5: Print the nodes

The function printNodes is provided as example to printout nodes coordinates, user’s Identification Number and associated coordinate system if any:

C
static void
printNodes(vis_Connect* connect)
{
    Vint i;
    Vint numnp;
    Vint nid, cid;
    Vint featype;
    Vdouble x[3];

    vis_ConnectNumber(connect, SYS_NODE, &numnp);
    printf("Number of nodes=    %d\n", numnp);
    /* nodes: coordinates, user id and
       displacement coordinate system id */
    printf("\nNodes\n");
    for (i = 1; i <= numnp; i++) {
        vis_ConnectCoordsdv(connect, 1, &i, (Vdouble(*)[3])x);
        vis_ConnectNodeAssoc(connect, VIS_USERID, 1, &i, &nid);
        vis_ConnectNodeAssoc(connect, VIS_CSYSID, 1, &i, &cid);
        printf("id= %d, cid= %d, x= %e %e %e\n", nid, cid, x[0], x[1], x[2]);
    }
}

The vis_ConnectNumber function returns the number of entities of the requested type SYS_NODE which in this case is the total number of nodes in the finite element model. The vis_ConnectCoordsdv function gives the node coordinates x, in double precision, for a set of nodes (only 1 node in that case). In the same way, the vis_ConnectNodeAssoc returns the node association value for a given type and for a given set of nodes indices (only 1 node in that case). For example, the VIS_USERID parameter requires the user ID of the node, and VIS_CSYSID requires the ID of the coordinate system associated with the node. If the node does not have its own coordinate system, 0 will be returned.

Step 6: Print the connectivity of the mesh

The function printElements is provided as example to printout elements connectivity and properties:

C
static void
static void
printElements(vis_Connect* connect)
{
    Vint i, j;
    Vint numel;
    Vint cid;
    Vint eid, pid, mid, partid;
    Vint feaType;
    Vint maxElemNode;
    Vint nix, *ix, *ux;
    Vint shape, maxi, maxj, maxk;

    vis_ConnectNumber(connect, SYS_ELEM, &numel);
    printf("Number of elements= %d\n", numel);
    /* elements: connectivity, user id, material and
       property id, etc. */
    printf("\nElements\n");
    vis_ConnectMaxElemNode(connect, &maxElemNode);
    /* allocate vectors for internal node ids and user ids */
    ix = (Vint*)malloc(maxElemNode * sizeof(Vint));
    ux = (Vint*)malloc(maxElemNode * sizeof(Vint));
    for (i = 1; i <= numel; i++) {
        vis_ConnectTopology(connect, i, &shape, &maxi, &maxj, &maxk);
        vis_ConnectElemNode(connect, i, &nix, ix);
        vis_ConnectElemAssoc(connect, VIS_USERID, 1, &i, &eid);
        vis_ConnectElemAssoc(connect, VIS_PARTID, 1, &i, &partid);
        vis_ConnectElemAssoc(connect, VIS_PROPID, 1, &i, &pid);
        vis_ConnectElemAssoc(connect, VIS_MATLID, 1, &i, &mid);
        vis_ConnectElemAssoc(connect, VIS_CSYSID, 1, &i, &cid);
        vis_ConnectElemAssoc(connect, VIS_FEATYPE, 1, &i, &feaType);
        printf("id= %d, partid= %d, pid= %d, mid= %d, cid= %d, nodes= %d\n", eid, partid, pid, mid, cid, nix);
        /* interpret shape */
        if (shape == SYS_SHAPEPOINT) {
            printf(" shape= Point(s):");
        }
        else if (shape == SYS_SHAPELINE) {
            printf(" shape= Line:");
        }
        else if (shape == SYS_SHAPETRI) {
            printf(" shape= Triangle:");
        }
        else if (shape == SYS_SHAPEQUAD) {
            printf(" shape= Quadrilateral:");
        }
        else if (shape == SYS_SHAPETET) {
            printf(" shape= Tetrahedron:");
        }
        else if (shape == SYS_SHAPEPYR) {
            printf(" shape= Pyramid:");
        }
        else if (shape == SYS_SHAPEWED) {
            printf(" shape= Pentahedron:");
        }
        else if (shape == SYS_SHAPEHEX) {
            printf(" shape= Hexahedron:");
        }
        else if (shape == SYS_SHAPEPOLYGON) {
            printf(" shape= Polygon:");
        }
        else if (shape == SYS_SHAPEPOLYHED) {
            printf(" shape= Polyhedron:");
        }
        /* interpret element type */
        if (feaType == VIS_ELEM_SOLID) {
            printf(" feaType= Solid element:");
        }
        else if (feaType == VIS_ELEM_SHELL) {
            printf(" feaType= Shell element:");
        }
        else if (feaType == VIS_ELEM_MEMBRANE) {
            printf(" feaType= Membrane element:");
        }
        else if (feaType == VIS_ELEM_BEAM) {
            printf(" feaType= Beam element:");
        }
        else if (feaType == VIS_ELEM_TRUSS) {
            printf(" feaType= Truss element:");
        }
        else if (feaType == VIS_ELEM_INFINITE) {
            printf(" feaType= Infinite element:");
        }
        else if (feaType == VIS_ELEM_GAP) {
            printf(" feaType= Gap element:");
        }
        else if (feaType == VIS_ELEM_JOINT) {
            printf(" shape= Joint element:");
        }
        else if (feaType == VIS_ELEM_SPRINGDASHPOT) {
            printf(" feaType= Spring Dashpot element:");
        }
        else if (feaType == VIS_ELEM_RIGID) {
            printf(" feaType= Rigid element:");
        }
        else if (feaType == VIS_ELEM_CONSTRAINT) {
            printf(" feaType= Constraint element:");
        }
        else if (feaType == VIS_ELEM_PLOT) {
            printf(" feaType= Plot element:");
        }
        else if (feaType == VIS_ELEM_MASS) {
            printf(" feaType= Structural Mass element:");
        }
        else if (feaType == VIS_ELEM_INTER) {
            printf(" feaType= Interaction element:");
        }
        else if (feaType == VIS_ELEM_SUPER) {
            printf(" feaType= Super-element:");
        }
        else if (feaType == VIS_ELEM_REINFORCEMENT) {
            printf(" feaType= Reinforcement element:");
        }
        printf("  maxi= %d, maxj= %d, maxk= %d\n", maxi, maxj, maxk);
        /* convert internal index to user id */
        vis_ConnectNodeAssoc(connect, VIS_USERID, nix, ix, ux);
        /* print element connectivity */
        printf(" connectivity=");
        for (j = 0; j < nix; j++) {
            printf(" %d", ux[j]);
        }
        printf("\n");
    }
    /* free vectors */
    free(ix);
    free(ux);
}

In the same way as in the previous step, the vis_ConnectNumber function invoked with the SYS_ELEM parameter returns the total number of elements in the finite element mesh. The vis_ConnectMaxElemNode function gives maximum nodes connected to element. This value is necessary to allocate the vector required for storing the connectivities, which will be done for each element using the vis_ConnectElemNode function. As with the nodes, the connect object can provide many element associations through the vis_ConnectElemAssoc function, such as the user ID, part ID, property ID, material ID, the element’s coordinate system and element type, using respectively the parameters VIS_USERID, VIS_PARTID, VIS_PROPID, VIS_MATLID, VIS_CSYSID and VIS_FEATYPE. The topology and connectivity of the element are accessible through the vis_ConnectElemNode and vis_ConnectNumber functions.

Step 7: Cleanup

Finally, We clear the model object, delete it, close the file and free all allocated resources:

C
/* delete objects registered in Model */
vis_ModelDelete(model);
/* destroy Model object itself */
vis_ModelEnd(model);

/* close library device and delete interface */
vdm_LManCloseFile(libraryManager);
vdm_LManEnd(libraryManager);
return 0;

The Model interface requires only two cleanup calls: vis_ModelDelete to delete all objects set inside the model and vdm_LManEnd to free the Model object. The Library Manager interface requires only two cleanup calls: vdm_LManCloseFile to close the file and vdm_LManEnd to free the Library Manager object.

Expected Output

When you run this example with a typical Universal file, you will see the list of nodes with their coordinates, as well as the elements with their connectivity and certain properties: Note: Only the first 5 and last entities have been included in the block below for clarity.

Number of nodes=    652

Nodes
id= 4001, cid= 0, x= 3.082680e+01 3.968360e+00 -1.003940e+00
id= 4002, cid= 0, x= 3.082680e+01 6.972330e+00 -1.003940e+00
id= 4003, cid= 0, x= 3.082680e+01 9.976310e+00 -1.003940e+00
id= 4004, cid= 0, x= 3.082680e+01 1.298030e+01 -1.003940e+00
......
......
id= 2245, cid= 0, x= -4.622050e+01 6.409450e+00 -2.007870e+00
id= 2244, cid= 0, x= -4.641730e+01 8.803150e+00 -2.007870e+00
id= 2243, cid= 0, x= -4.661420e+01 1.119680e+01 -2.007870e+00
id= 2242, cid= 0, x= -4.681100e+01 1.359060e+01 -2.007870e+00
id= 2003, cid= 0, x= -4.700790e+01 1.598430e+01 -2.007870e+00
Number of elements= 604

Elements
id= 11001, partid= 1001, pid= 1001, mid= 1, cid= 0, nodes= 2
 shape= Line: feaType= Beam element:  maxi= 0, maxj= 0, maxk= 0
 connectivity= 2012 2021
id= 11002, partid= 1001, pid= 1001, mid= 1, cid= 0, nodes= 2
 shape= Line: feaType= Beam element:  maxi= 0, maxj= 0, maxk= 0
 connectivity= 2021 2020
id= 11003, partid= 1001, pid= 1001, mid= 1, cid= 0, nodes= 2
 shape= Line: feaType= Beam element:  maxi= 0, maxj= 0, maxk= 0
 connectivity= 2020 2019
id= 12001, partid= 1002, pid= 1002, mid= 1, cid= 0, nodes= 2
 shape= Line: feaType= Beam element:  maxi= 0, maxj= 0, maxk= 0
 connectivity= 2019 2018
id= 12002, partid= 1002, pid= 1002, mid= 1, cid= 0, nodes= 2
 shape= Line: feaType= Beam element:  maxi= 0, maxj= 0, maxk= 0
 connectivity= 2018 2033
 ......
 ......
 id= 212, partid= 1, pid= 1, mid= 1, cid= -9, nodes= 3
  shape= Triangle: feaType= Shell element:  maxi= 0, maxj= 0, maxk= 0
  connectivity= 260 251 256
 id= 2003, partid= 1, pid= 1, mid= 1, cid= -9, nodes= 3
  shape= Triangle: feaType= Shell element:  maxi= 0, maxj= 0, maxk= 0
  connectivity= 2007 2005 2004
 id= 2004, partid= 1, pid= 1, mid= 1, cid= -9, nodes= 3
  shape= Triangle: feaType= Shell element:  maxi= 0, maxj= 0, maxk= 0
  connectivity= 2007 2006 2005
 id= 2211, partid= 1, pid= 1, mid= 1, cid= -9, nodes= 3
  shape= Triangle: feaType= Shell element:  maxi= 0, maxj= 0, maxk= 0
  connectivity= 2246 2250 2249
 id= 2212, partid= 1, pid= 1, mid= 1, cid= -9, nodes= 3
  shape= Triangle: feaType= Shell element:  maxi= 0, maxj= 0, maxk= 0
  connectivity= 2246 2241 2250

Complete Source Code

The complete source code for this example can be found at: src/sam/vdm/exam/exam2.cpp

You can also view the full source here:

  1#include <stdlib.h>
  2#include "sam/base/base.h"
  3#include "sam/vis/visdata.h"
  4#include "sam/vdm/vdm.h"
  5#include "sam/base/license.h"
  6#include "sam/hoops_license.h"
  7
  8static void
  9printNodes(vis_Connect* connect);
 10static void
 11printElements(vis_Connect* connect);
 12
 13/*----------------------------------------------------------------------
 14                      Read and Print Model Data
 15----------------------------------------------------------------------*/
 16int
 17main(int argc, char** argv)
 18{
 19    char inputfile[256];
 20    vis_Model* model = NULL;
 21    vis_Connect* connect = NULL;
 22    vdm_LMan* lman = NULL;
 23
 24    if (argc < 2) {
 25        fprintf(stderr, "Usage: %s inputfile\n", argv[0]);
 26        fprintf(stderr, " inputfile is blank, 'bumper.unv' is assumed\n");
 27        strcpy(inputfile, "bumper.unv");
 28    }
 29    else {
 30        strcpy(inputfile, argv[1]);
 31    }
 32
 33    vsy_LicenseValidate(HOOPS_LICENSE);
 34
 35    /* Open file */
 36    lman = vdm_LManBegin();
 37    vdm_LManOpenFile(lman, inputfile, NULL);
 38
 39    /* check for error */
 40    Vint ierr = vdm_LManError(lman);
 41    if (ierr) {
 42        fprintf(stderr, "Error: opening file %s\n", inputfile);
 43        vdm_LManCloseFile(lman);
 44        vdm_LManEnd(lman);
 45        exit(1);
 46    }
 47
 48    /* instance model object for finite element model */
 49    model = vis_ModelBegin();
 50
 51    /* use Library Manager object to load model */
 52    vdm_LManLoadModel(lman, model);
 53    if (vdm_LManError(lman)) {
 54        fprintf(stderr, "Error: Unable to load model information\n");
 55        exit(1);
 56    }
 57
 58    /* get Connect object and print nodes and elements */
 59    vis_ModelGetObject(model, VIS_CONNECT, (Vobject**)&connect);
 60    if (connect != NULL) {
 61        printNodes(connect);
 62        printElements(connect);
 63    }
 64    /* delete objects registered in Model */
 65    vis_ModelDelete(model);
 66    /* destroy Model object itself */
 67    vis_ModelEnd(model);
 68    /* close library device and delete interface */
 69    vdm_LManCloseFile(lman);
 70    vdm_LManEnd(lman);
 71    return 0;
 72}
 73
 74/*----------------------------------------------------------------------
 75                      print nodes
 76----------------------------------------------------------------------*/
 77static void
 78printNodes(vis_Connect* connect)
 79{
 80    Vint i;
 81    Vint numnp;
 82    Vint nid, cid;
 83    Vint featype;
 84    Vdouble x[3];
 85
 86    vis_ConnectNumber(connect, SYS_NODE, &numnp);
 87    printf("Number of nodes=    %d\n", numnp);
 88    /* nodes: coordinates, user id and
 89       displacement coordinate system id */
 90    printf("\nNodes\n");
 91    for (i = 1; i <= numnp; i++) {
 92        vis_ConnectCoordsdv(connect, 1, &i, (Vdouble(*)[3])x);
 93        vis_ConnectNodeAssoc(connect, VIS_USERID, 1, &i, &nid);
 94        vis_ConnectNodeAssoc(connect, VIS_CSYSID, 1, &i, &cid);
 95        printf("id= %d, cid= %d, x= %e %e %e\n", nid, cid, x[0], x[1], x[2]);
 96        /* check for scalar node */
 97        vis_ConnectNodeAssoc(connect, VIS_FEATYPE, 1, &i, &featype);
 98        if (featype == SYS_NODE_SCALAR) {
 99            printf("featype= Scalar node\n");
100        }
101    }
102}
103
104/*----------------------------------------------------------------------
105                      print elements
106----------------------------------------------------------------------*/
107static void
108printElements(vis_Connect* connect)
109{
110    Vint i, j;
111    Vint numel;
112    Vint cid;
113    Vint eid, pid, mid, partid;
114    Vint featype;
115    Vint maxelemnode;
116    Vint nix, *ix, *ux;
117    Vint shape, maxi, maxj, maxk;
118
119    vis_ConnectNumber(connect, SYS_ELEM, &numel);
120    printf("Number of elements= %d\n", numel);
121    /* elements: connectivity, user id, material and
122       property id, etc. */
123    printf("\nElements\n");
124    vis_ConnectMaxElemNode(connect, &maxelemnode);
125    /* allocate vectors for internal node ids and user ids */
126    ix = (Vint*)malloc(maxelemnode * sizeof(Vint));
127    ux = (Vint*)malloc(maxelemnode * sizeof(Vint));
128    for (i = 1; i <= numel; i++) {
129        vis_ConnectTopology(connect, i, &shape, &maxi, &maxj, &maxk);
130        vis_ConnectElemNode(connect, i, &nix, ix);
131        vis_ConnectElemAssoc(connect, VIS_USERID, 1, &i, &eid);
132        vis_ConnectElemAssoc(connect, VIS_PARTID, 1, &i, &partid);
133        vis_ConnectElemAssoc(connect, VIS_PROPID, 1, &i, &pid);
134        vis_ConnectElemAssoc(connect, VIS_MATLID, 1, &i, &mid);
135        vis_ConnectElemAssoc(connect, VIS_CSYSID, 1, &i, &cid);
136        vis_ConnectElemAssoc(connect, VIS_FEATYPE, 1, &i, &featype);
137        printf("id= %d, partid= %d, pid= %d, mid= %d, cid= %d, nodes= %d\n", eid, partid, pid, mid, cid, nix);
138        /* interpret shape */
139        if (shape == SYS_SHAPEPOINT) {
140            printf(" shape= Point(s):");
141        }
142        else if (shape == SYS_SHAPELINE) {
143            printf(" shape= Line:");
144        }
145        else if (shape == SYS_SHAPETRI) {
146            printf(" shape= Triangle:");
147        }
148        else if (shape == SYS_SHAPEQUAD) {
149            printf(" shape= Quadrilateral:");
150        }
151        else if (shape == SYS_SHAPETET) {
152            printf(" shape= Tetrahedron:");
153        }
154        else if (shape == SYS_SHAPEPYR) {
155            printf(" shape= Pyramid:");
156        }
157        else if (shape == SYS_SHAPEWED) {
158            printf(" shape= Pentahedron:");
159        }
160        else if (shape == SYS_SHAPEHEX) {
161            printf(" shape= Hexahedron:");
162        }
163        else if (shape == SYS_SHAPEPOLYGON) {
164            printf(" shape= Polygon:");
165        }
166        else if (shape == SYS_SHAPEPOLYHED) {
167            printf(" shape= Polyhedron:");
168        }
169        printf("  maxi= %d, maxj= %d, maxk= %d\n", maxi, maxj, maxk);
170        /* convert internal index to user id */
171        vis_ConnectNodeAssoc(connect, VIS_USERID, nix, ix, ux);
172        /* print element connectivity */
173        printf(" connectivity=");
174        for (j = 0; j < nix; j++) {
175            printf(" %d", ux[j]);
176        }
177        printf("\n");
178    }
179    /* free vectors */
180    free(ix);
181    free(ux);
182}