Read and Print Model Data
This example illustrates loading a Model object with a finite element model residing on an external file and then traversing and printing the node coordinates and element connectivity contained in the Mesh object. The finite element model may reside on any external file in a format supported by HOOPS Access. 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.
Quick Navigation:
- Overview
- Step 1: Initialize and Setup
- Step 2: Open File with DataSource and check for errors
- Step 3: Load the model and check for errors
- Step 4: Get the mesh object and print nodes and elements
- Step 5: Print the nodes
- Step 6: Print the connectivity of the mesh
- Complete Source Code
Overview
The example performs the following main tasks:
- Parse command line arguments, set input file and validate license
- Open the file using DataSource, check for errors and handle them appropriately
- Load the model and check for errors
- Get the mesh object and print nodes and elements
- Helper functions to print nodes and elements
- Print the connectivity of the mesh
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 "samcpp/core/core.h"
#include "samcpp/access/access.h"
#include "sam/hoops_license.h"
#include <vector>
#include <iostream>
#include <iomanip>
static void
print_nodes(cae::core::MeshPtr& mesh);
static void
print_elements(cae::core::MeshPtr& mesh);
/*----------------------------------------------------------------------
Read and Print Model Data
----------------------------------------------------------------------*/
int
main(int argc, char** argv)
{
char inputfile[cae::core::MAX_NAME_LENGTH] = {};
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " inputfile\n";
std::cerr << " inputfile is blank, 'bumper.unv' is assumed\n";
strcpy(inputfile, "bumper.unv");
}
else {
strcpy(inputfile, argv[1]);
}
cae::core::license::validate(HOOPS_LICENSE);
The program provides helpful information about the mesh in the “bumper.unv” file which is provided along with the SDK.
The license is validated using the validate() function.
Step 2: Open File with DataSource and check for errors
Next, we create a DataSource and open the input file:
// Open file
cae::access::DataSource dataSource;
cae::core::Status status = dataSource.openFile(inputfile, NULL);
// Check for error
if (!status) {
std::cerr << "Error: opening file " << inputfile << '\n';
exit(1);
}
The DataSource provides a high-level interface for file operations using
openFile(), automatically detecting
the file format. Proper error checking is essential when working with file operations.
Step 3: Load the model and check for errors
Now we instantiate the model and ask the DataSource to load the finite element model information:
// Load the model from the file
cae::core::Model model;
status = dataSource.loadModel(&model);
if (!status) {
std::cerr << "Error: Unable to load model information\n";
exit(1);
}
The DataSource’s loadModel() method reads all the model data contained in the file and populates the Model object.
The 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 mesh object and print nodes and elements
Now we get the mesh object from the model and use helper functions to print its contents:
// Get the mesh and print nodes and elements
cae::core::MeshPtr mesh;
model.getMesh(mesh);
if (mesh != NULL) {
print_nodes(mesh);
print_elements(mesh);
}
return 0;
The Mesh manages all data related to the finite element mesh: the coordinates, the connectivities,
and the adjacency properties. The getMesh() method gets a pointer to the Mesh object from the model.
Step 5: Print the nodes
The function print_nodes is provided as an example to print out node coordinates, user’s Identification Number
and associated coordinate system if any:
static void
print_nodes(cae::core::MeshPtr& mesh)
{
int nodeCount = 0;
mesh->getEntityCount(cae::core::EntityType::NODE, &nodeCount);
std::cout << "Number of nodes= " << nodeCount << '\n';
std::cout << "\nNodes\n";
double coordinates[3]{0.0, 0.0, 0.0};
auto previousFlags = std::cout.flags();
std::cout << std::scientific;
for (int i = 1; i <= nodeCount; i++) {
mesh->getCoordinates(1, &i, (double (*)[3])coordinates);
int nodeId = 0;
mesh->getNodeAssociation<cae::core::NodeAssociationType::PART_ID>(1, &i, &nodeId);
int coordinateSystemId = 0;
mesh->getNodeAssociation<cae::core::NodeAssociationType::COORDINATE_SYSTEM_ID>(1, &i, &coordinateSystemId);
std::cout << "id= " << nodeId << ", cid= " << coordinateSystemId << ", x= " << coordinates[0] << ' ' << coordinates[1]
<< ' ' << coordinates[2] << '\n';
}
std::cout.flags(previousFlags);
}
The getEntityCount() method returns the number of entities of the requested type NODE.
The getCoordinates() method gives the node coordinates for a set of nodes (only 1 node in each iteration).
The getNodeAssociation() method returns the node association value for a given type. For example,
USER_ID requests the user ID of the element, and COORDINATE_SYSTEM_ID
requests the ID of the coordinate system associated with the node.
Step 6: Print the connectivity of the mesh
The function print_elements is provided as an example to print out element connectivity and properties:
static void
print_elements(cae::core::MeshPtr& mesh)
{
int elementCount = 0;
mesh->getEntityCount(cae::core::EntityType::ELEMENT, &elementCount);
std::cout << "Number of elements= " << elementCount << '\n';
std::cout << "\nElements\n";
int maxNodesInElement = 0;
mesh->getMaxElementNodes(&maxNodesInElement);
/* allocate vectors for internal node ids and user ids */
std::vector<int> nodeIndexes(maxNodesInElement, 0);
std::vector<int> nodeIds(maxNodesInElement, 0);
for (int i = 1; i <= elementCount; i++) {
cae::core::ElementShape shape;
int maxi = 0, maxj = 0, maxk = 0;
mesh->getTopology(i, &shape, &maxi, &maxj, &maxk);
int nodesInElement = 0;
mesh->getElementNodes(i, &nodesInElement, nodeIndexes.data());
int elementId = 0;
int partId = 0;
int propertyId = 0;
int materialId = 0;
int coordinateSystemId = 0;
cae::core::ElementType elementType;
mesh->getElementAssociation<cae::core::ElementAssociationType::USER_ID>(1, &i, &elementId);
mesh->getElementAssociation<cae::core::ElementAssociationType::PART_ID>(1, &i, &partId);
mesh->getElementAssociation<cae::core::ElementAssociationType::PROPERTY_ID>(1, &i, &propertyId);
mesh->getElementAssociation<cae::core::ElementAssociationType::MATERIAL_ID>(1, &i, &materialId);
mesh->getElementAssociation<cae::core::ElementAssociationType::COORDINATE_SYSTEM_ID>(1, &i, &coordinateSystemId);
mesh->getElementAssociation<cae::core::ElementAssociationType::ELEMENT_TYPE>(1, &i, &elementType);
std::cout << "id= " << elementId << ", partid= " << partId << ", pid= " << propertyId << ", mid= " << materialId
<< ", cid= " << coordinateSystemId << ", nodes= " << nodesInElement << '\n';
/* interpret shape */
if (shape == cae::core::ElementShape::POINT) {
std::cout << " shape= Point(s):";
}
else if (shape == cae::core::ElementShape::LINE) {
std::cout << " shape= Line:";
}
else if (shape == cae::core::ElementShape::TRIANGLE) {
std::cout << " shape= Triangle:";
}
else if (shape == cae::core::ElementShape::QUADRILATERAL) {
std::cout << " shape= Quadrilateral:";
}
else if (shape == cae::core::ElementShape::TETRAHEDRON) {
std::cout << " shape= Tetrahedron:";
}
else if (shape == cae::core::ElementShape::PYRAMID) {
std::cout << " shape= Pyramid:";
}
else if (shape == cae::core::ElementShape::WEDGE) {
std::cout << " shape= Pentahedron:";
}
else if (shape == cae::core::ElementShape::HEXAHEDRON) {
std::cout << " shape= Hexahedron:";
}
else if (shape == cae::core::ElementShape::POLYGON) {
std::cout << " shape= Polygon:";
}
else if (shape == cae::core::ElementShape::POLYHEDRON) {
std::cout << " shape= Polyhedron:";
}
std::cout << " maxi= " << maxi << ", maxj= " << maxj << ", maxk= " << maxk << '\n';
// Convert internal index to user id
mesh->getNodeAssociation<cae::core::NodeAssociationType::USER_ID>(nodesInElement, nodeIndexes.data(), nodeIds.data());
// Print element connectivity
std::cout << " connectivity=";
for (int j = 0; j < nodesInElement; j++) {
std::cout << ' ' << nodeIds[j];
}
std::cout << '\n';
}
}
The getEntityCount() method with ELEMENT returns the total number of elements.
The getMaxElementNodes() method returns the maximum number of nodes connected to an element.
The getElementAssociation() method provides many element associations, such as the user ID, part ID,
property ID, material ID, and coordinate system ID.
The topology and connectivity of the element are accessible through the getTopology() and
getElementNodes() methods.
Complete Source Code
The complete source code for this example can be found at: src/sam/vdm/exam/tutorial_read_model_data.cpp
You can also view the full source here:
1#include "samcpp/core/core.h"
2#include "samcpp/access/access.h"
3#include "sam/hoops_license.h"
4#include <vector>
5#include <iostream>
6#include <iomanip>
7
8static void
9print_nodes(cae::core::MeshPtr& mesh);
10static void
11print_elements(cae::core::MeshPtr& mesh);
12
13/*----------------------------------------------------------------------
14 Read and Print Model Data
15----------------------------------------------------------------------*/
16int
17main(int argc, char** argv)
18{
19 char inputfile[cae::core::MAX_NAME_LENGTH] = {};
20
21 if (argc < 2) {
22 std::cerr << "Usage: " << argv[0] << " inputfile\n";
23 std::cerr << " inputfile is blank, 'bumper.unv' is assumed\n";
24 strcpy(inputfile, "bumper.unv");
25 }
26 else {
27 strcpy(inputfile, argv[1]);
28 }
29
30 cae::core::license::validate(HOOPS_LICENSE);
31
32 // Open file
33 cae::access::DataSource dataSource;
34 cae::core::Status status = dataSource.openFile(inputfile, NULL);
35
36 // Check for error
37 if (!status) {
38 std::cerr << "Error: opening file " << inputfile << '\n';
39 exit(1);
40 }
41
42 // Load the model from the file
43 cae::core::Model model;
44 status = dataSource.loadModel(&model);
45 if (!status) {
46 std::cerr << "Error: Unable to load model information\n";
47 exit(1);
48 }
49
50 // Get the mesh and print nodes and elements
51 cae::core::MeshPtr mesh;
52 model.getMesh(mesh);
53 if (mesh != NULL) {
54 print_nodes(mesh);
55 print_elements(mesh);
56 }
57
58 return 0;
59}
60
61static void
62print_nodes(cae::core::MeshPtr& mesh)
63{
64 int nodeCount = 0;
65 mesh->getEntityCount(cae::core::EntityType::NODE, &nodeCount);
66 std::cout << "Number of nodes= " << nodeCount << '\n';
67 std::cout << "\nNodes\n";
68 double coordinates[3]{0.0, 0.0, 0.0};
69 auto previousFlags = std::cout.flags();
70 std::cout << std::scientific;
71 for (int i = 1; i <= nodeCount; i++) {
72 mesh->getCoordinates(1, &i, (double (*)[3])coordinates);
73 int nodeId = 0;
74 mesh->getNodeAssociation<cae::core::NodeAssociationType::USER_ID>(1, &i, &nodeId);
75 int coordinateSystemId = 0;
76 mesh->getNodeAssociation<cae::core::NodeAssociationType::COORDINATE_SYSTEM_ID>(1, &i, &coordinateSystemId);
77 std::cout << "id= " << nodeId << ", cid= " << coordinateSystemId << ", x= " << coordinates[0] << ' ' << coordinates[1]
78 << ' ' << coordinates[2] << '\n';
79 }
80 std::cout.flags(previousFlags);
81}
82
83static void
84print_elements(cae::core::MeshPtr& mesh)
85{
86 int elementCount = 0;
87 mesh->getEntityCount(cae::core::EntityType::ELEMENT, &elementCount);
88 std::cout << "Number of elements= " << elementCount << '\n';
89 std::cout << "\nElements\n";
90 int maxNodesInElement = 0;
91 mesh->getMaxElementNodes(&maxNodesInElement);
92 /* allocate vectors for internal node ids and user ids */
93 std::vector<int> nodeIndexes(maxNodesInElement, 0);
94 std::vector<int> nodeIds(maxNodesInElement, 0);
95 for (int i = 1; i <= elementCount; i++) {
96 cae::core::ElementShape shape;
97 int maxi = 0, maxj = 0, maxk = 0;
98 mesh->getTopology(i, &shape, &maxi, &maxj, &maxk);
99 int nodesInElement = 0;
100 mesh->getElementNodes(i, &nodesInElement, nodeIndexes.data());
101 int elementId = 0;
102 int partId = 0;
103 int propertyId = 0;
104 int materialId = 0;
105 int coordinateSystemId = 0;
106 cae::core::ElementType elementType;
107 mesh->getElementAssociation<cae::core::ElementAssociationType::USER_ID>(1, &i, &elementId);
108 mesh->getElementAssociation<cae::core::ElementAssociationType::PART_ID>(1, &i, &partId);
109 mesh->getElementAssociation<cae::core::ElementAssociationType::PROPERTY_ID>(1, &i, &propertyId);
110 mesh->getElementAssociation<cae::core::ElementAssociationType::MATERIAL_ID>(1, &i, &materialId);
111 mesh->getElementAssociation<cae::core::ElementAssociationType::COORDINATE_SYSTEM_ID>(1, &i, &coordinateSystemId);
112 mesh->getElementAssociation<cae::core::ElementAssociationType::ELEMENT_TYPE>(1, &i, &elementType);
113 std::cout << "id= " << elementId << ", partid= " << partId << ", pid= " << propertyId << ", mid= " << materialId
114 << ", cid= " << coordinateSystemId << ", nodes= " << nodesInElement << '\n';
115 /* interpret shape */
116 if (shape == cae::core::ElementShape::POINT) {
117 std::cout << " shape= Point(s):";
118 }
119 else if (shape == cae::core::ElementShape::LINE) {
120 std::cout << " shape= Line:";
121 }
122 else if (shape == cae::core::ElementShape::TRIANGLE) {
123 std::cout << " shape= Triangle:";
124 }
125 else if (shape == cae::core::ElementShape::QUADRILATERAL) {
126 std::cout << " shape= Quadrilateral:";
127 }
128 else if (shape == cae::core::ElementShape::TETRAHEDRON) {
129 std::cout << " shape= Tetrahedron:";
130 }
131 else if (shape == cae::core::ElementShape::PYRAMID) {
132 std::cout << " shape= Pyramid:";
133 }
134 else if (shape == cae::core::ElementShape::WEDGE) {
135 std::cout << " shape= Pentahedron:";
136 }
137 else if (shape == cae::core::ElementShape::HEXAHEDRON) {
138 std::cout << " shape= Hexahedron:";
139 }
140 else if (shape == cae::core::ElementShape::POLYGON) {
141 std::cout << " shape= Polygon:";
142 }
143 else if (shape == cae::core::ElementShape::POLYHEDRON) {
144 std::cout << " shape= Polyhedron:";
145 }
146 std::cout << " maxi= " << maxi << ", maxj= " << maxj << ", maxk= " << maxk << '\n';
147 // Convert internal index to user id
148 mesh->getNodeAssociation<cae::core::NodeAssociationType::USER_ID>(nodesInElement, nodeIndexes.data(), nodeIds.data());
149 // Print element connectivity
150 std::cout << " connectivity=";
151 for (int j = 0; j < nodesInElement; j++) {
152 std::cout << ' ' << nodeIds[j];
153 }
154 std::cout << '\n';
155 }
156}
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 HOOPS Access. 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.
Quick Navigation:
- Overview
- Step 1: Initialize and Setup
- Step 2: Open File with Library Manager and check for errors
- Step 3: Load the model and check for errors
- Step 4: Get the connect object and check for errors
- Step 5: Print the nodes
- Step 6: Print the connectivity of the mesh
- Step 7: Cleanup
- Complete Source Code
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.
The license is validated using the vsy_LicenseValidate() function.
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 instantiate the model and the library manager is asked to read the finite element model information 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 also provides 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 the
connect object could not be extracted from the model.
Step 5: Print the nodes
The function printNodes is provided as example to print out node 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 node 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 print out element connectivity and properties:
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 returns the maximum number of nodes connected to an
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.
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}
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