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:
- Parse command line arguments, set input file and validate license
- Open the file using Library Manager, check for errors and handle them appropriately
- Load the model and check for errors
- Get the connect object and check for errors
- Print the list of nodes with their coordinates and their associated coordinate system, if any
- Print the connectivity of the mesh
- 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:
#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:
/* 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:
/* 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:
/* 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:
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:
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:
/* 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}