MOAB: Mesh Oriented datABase  (version 5.5.0)
imoab_test.c File Reference
#include "moab/MOABConfig.h"
#include "moab/iMOAB.h"
#include <string.h>
+ Include dependency graph for imoab_test.c:

Go to the source code of this file.

Macros

#define CHECKRC(rc, message)
 

Functions

int main (int argc, char *argv[])
 

Macro Definition Documentation

◆ CHECKRC

#define CHECKRC (   rc,
  message 
)
Value:
if( 0 != ( rc ) ) \
{ \
printf( "Error: %s.\n", message ); \
return 1; \
}

Definition at line 10 of file imoab_test.c.

Function Documentation

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 17 of file imoab_test.c.

18 {
19  /* Declarations */
20  ErrCode rc;
21  int nprocs = 1, rank = 0;
22  char filen[1024] = "";
23  int i, j, k;
24 
25  int irank = 0, num_tags_to_sync = 1;
26  int* ranks;
27 
28  int appID, appDupID;
29  iMOAB_AppID pid;
30  iMOAB_AppID pidDup;
31  int compid = 11, compdupid = 12;
32 
33  int num_global_vertices = 0, num_global_elements = 0, num_dimension = 0, num_parts = 0;
34  int nverts[3], nelem[3], nblocks[3], nsbc[3], ndbc[3];
35 
36  iMOAB_GlobalID* vGlobalID;
37  int* vranks;
38  double* coords;
39  int size_coords;
40 
41 #ifdef MOAB_HAVE_MPI
42  const char* read_opts = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS";
43  int num_ghost_layers[1] = { 1 };
44 #else
45  const char* read_opts = "";
46  int num_ghost_layers[1] = { 0 };
47 #endif
48 
49  iMOAB_GlobalID* gbIDs;
50  int tagIndex[2];
51  int entTypes[2] = { 0, 1 }; /* first is on vertex, second is on elements; */
52  int tagTypes[2] = { DENSE_INTEGER, DENSE_DOUBLE };
53  int num_components = 1;
54 
55  iMOAB_GlobalID *element_global_IDs, *block_IDs;
56  int vertices_per_element, num_elements_in_block;
57  int conn[27], nv, eindex;
58 
59  int* int_tag_vals;
60  double* double_tag_vals;
61 
62  int local_index = 0; /* test element with local index 0 */
63  int num_adjacent_elements = 10; /* we can have maximum 6 actually */
64  iMOAB_LocalID adjacent_element_IDs[10], *element_connectivity, *local_element_ID;
65  int size_conn, *element_ownership;
66  iMOAB_GlobalID* global_element_ID;
67 
68  iMOAB_LocalID *vertBC_ID, *surfBC_ID;
69  int *vertBC_value, *ref_surf, *bc_value;
70 
71  char *outputFile, *writeOptions;
72 
73 #ifdef MOAB_HAVE_MPI
74  MPI_Comm comm;
75  MPI_Init( &argc, &argv );
76 
77  comm = MPI_COMM_WORLD;
78  MPI_Comm_size( comm, &nprocs );
79  MPI_Comm_rank( comm, &rank );
80 #endif
81 
82 #ifdef MOAB_HAVE_HDF5
83  strcpy( filen, MOAB_MESH_DIR );
84  strcat( filen, "unittest/io/p8ex1.h5m" );
85 #endif
86 
87  if( argc > 1 ) strcpy( filen, argv[1] );
88 
89  if( !strlen( filen ) )
90  {
91  printf( "Invalid filename specified at command line.\n" );
92  return 1;
93  }
94  /*
95  * MOAB needs to be initialized; A MOAB instance will be created, and will be used by each
96  * application in this framework. There is no parallel context yet.
97  */
98  rc = iMOAB_Initialize( argc, argv );
99  CHECKRC( rc, "failed to initialize MOAB" );
100 
101  /*
102  * Header information is cheap to retrieve from an hdf5 file; it can be called by each process
103  * or can be called by one master task and broadcasted. The hdf5 file has to be in MOAB native
104  * format, and has to be partitioned in advance. There should be at least as many partitions in
105  * the file as number of tasks in the communicator.
106  */
107  rc = iMOAB_ReadHeaderInfo( filen, &num_global_vertices, &num_global_elements, &num_dimension, &num_parts );
108  CHECKRC( rc, "failed to read header info" );
109 
110  if( 0 == rank )
111  {
112  printf( "file %s has %d vertices, %d elements, %d parts in partition\n", filen, num_global_vertices,
113  num_global_elements, num_parts );
114  }
115 
116  pid = &appID;
117  pidDup = &appDupID;
118 
119  /*
120  * Each application has to be registered once. A mesh set and a parallel communicator will be
121  * associated with each application. A unique application id will be returned, and will be used
122  * for all future mesh operations/queries.
123  */
124  rc = iMOAB_RegisterApplication( "MBAPP",
125 #ifdef MOAB_HAVE_MPI
126  &comm,
127 #endif
128  &compid, pid );
129  CHECKRC( rc, "failed to register application" );
130 
131  rc = iMOAB_RegisterApplication( "MBDUPAPP",
132 #ifdef MOAB_HAVE_MPI
133  &comm,
134 #endif
135  &compdupid, pidDup );
136  CHECKRC( rc, "failed to register duplicate application" );
137 
138  /*
139  * Loading the mesh is a parallel IO operation. Ghost layers can be exchanged too, and default
140  * MOAB sets are augmented with ghost elements. By convention, blocks correspond to MATERIAL_SET
141  * sets, side sets with NEUMANN_SET sets, node sets with DIRICHLET_SET sets. Each element and
142  * vertex entity should have a GLOBAL ID tag in the file, which will be available for visible
143  * entities
144  */
145  rc = iMOAB_LoadMesh( pid, filen, read_opts, num_ghost_layers );
146  CHECKRC( rc, "failed to load mesh" );
147 
148  rc = iMOAB_LoadMesh( pidDup, filen, read_opts, num_ghost_layers );
149  CHECKRC( rc, "failed to load mesh" );
150 
151  rc = iMOAB_SetGlobalInfo( pid, &num_global_vertices, &num_global_elements );
152  CHECKRC( rc, "failed to set global info" );
153 
154  /*
155  * Each process in the communicator will have access to a local mesh instance, which will
156  * contain the original cells in the local partition and ghost entities. Number of vertices,
157  * primary cells, visible blocks, number of sidesets and nodesets boundary conditions will be
158  * returned in size 3 arrays, for local, ghost and total numbers.
159  */
160  rc = iMOAB_GetMeshInfo( pid, nverts, nelem, nblocks, nsbc, ndbc );
161  CHECKRC( rc, "failed to get mesh info" );
162 
163  vGlobalID = (iMOAB_GlobalID*)malloc( nverts[2] * sizeof( iMOAB_GlobalID ) );
164  /*
165  * All visible vertices have a unique global ID. All arrays are allocated by client.
166  * Currently, global ID is a 32 bit integer, total number of visible vertices was returned by
167  * iMOAB_GetMeshInfo
168  */
169  rc = iMOAB_GetVertexID( pid, &nverts[2], vGlobalID );
170  CHECKRC( rc, "failed to get vertex id info" );
171 
172  vranks = (int*)malloc( nverts[2] * sizeof( int ) );
173  /*
174  * In MOAB terminology, a vertex can be owned, shared or ghost. An owned vertex will be
175  * owned by the current process. A shared vertex appears at the interface between partitions, it
176  * can be owned by another process, while a ghost vertex is owned by another process always. All
177  * vertex arrays have a natural local order, in which the ghost vertices are at the end of the
178  * arrays. The local index of the vertex will vary from 0 to number of visible vertices (in this
179  * example nverts[2]-1)
180  */
181  rc = iMOAB_GetVertexOwnership( pid, &nverts[2], vranks );
182  CHECKRC( rc, "failed to get vertex ranks" );
183 
184  coords = (double*)malloc( 3 * nverts[2] * sizeof( double ) );
185  size_coords = 3 * nverts[2];
186  /*
187  * Coordinates are returned interleaved, for all visible vertices. Size is dimension times
188  * number of visible vertices
189  */
190  rc = iMOAB_GetVisibleVerticesCoordinates( pid, &size_coords, coords );
191  CHECKRC( rc, "failed to get coordinates" );
192 
193  /*
194  * Block IDs correspond to MATERIAL_SET tag values in hdf5 file
195  * They also correspond to block IDs in a Cubit model.
196  * Local visible blocks might contain ghost cells, owned by other
197  * processes.
198  *
199  * Inside MOAB, a block will correspond to a meshset with a MATERIAL_SET tag,
200  * with value the block ID.
201  * A MATERIAL_SET tag in moab if SPARSE and type INTEGER.
202  */
203  gbIDs = (iMOAB_GlobalID*)malloc( nblocks[2] * sizeof( iMOAB_GlobalID ) );
204  rc = iMOAB_GetBlockID( pid, &nblocks[2], gbIDs );
205  CHECKRC( rc, "failed to get block info" );
206 
207  /*
208  * The 2 tags used in this example exist in the file, already.
209  * If a user needs a new tag, it can be defined with the same call as this one
210  * this method, iMOAB_DefineTagStorage, will return a local index for the tag.
211  * The name of the tag is case sensitive.
212  * This method is collective.
213  */
214  rc = iMOAB_DefineTagStorage( pid, "INTFIELD", &tagTypes[0], &num_components, &tagIndex[0] );
215  CHECKRC( rc, "failed to get tag INTFIELD " );
216  rc = iMOAB_DefineTagStorage( pid, "DFIELD", &tagTypes[1], &num_components, &tagIndex[1] );
217  CHECKRC( rc, "failed to get tag DFIELD " );
218 
219  /*
220  * Synchronize one of the tags only, just to see what happens;
221  * Tags are not exchanged for ghost entities by default. The user has to explicitly
222  * synchronize them with a call like this one. The tags to synchronize are referenced by the
223  * index returned at their "definition" with iMOAB_DefineTagStorage method.
224  */
225  rc = iMOAB_SynchronizeTags( pid, &num_tags_to_sync, &tagIndex[0], &tagTypes[0] );
226  CHECKRC( rc, "failed to sync tag INTFIELD " );
227 
228  for( irank = 0; irank < nprocs; irank++ )
229  {
230  if( irank == rank )
231  {
232  /* printf some of the block info */
233  printf( "on rank %d, there are \n"
234  " %3d visible vertices of which %3d local %3d ghost \n"
235  " %3d visible elements of which %3d owned %3d ghost \n"
236  " %3d visible blocks\n"
237  " %3d visible neumann BCs\n"
238  " %3d visible dirichlet BCs\n",
239  rank, nverts[2], nverts[0], nverts[1], nelem[2], nelem[0], nelem[1], nblocks[2], nsbc[2], ndbc[2] );
240 
241  /* print some of the vertex id infos */
242  printf( "on rank %d vertex info:\n", rank );
243  for( i = 0; i < nverts[2]; i++ )
244  printf( " vertex local id: %3d, rank ID:%d global ID: %3d coords: %g, %g, %g\n", i, vranks[i],
245  vGlobalID[i], coords[3 * i], coords[3 * i + 1], coords[3 * i + 2] );
246 
247  element_global_IDs = (iMOAB_GlobalID*)malloc( nelem[2] * sizeof( iMOAB_GlobalID ) );
248  block_IDs = (iMOAB_GlobalID*)malloc( nelem[2] * sizeof( iMOAB_GlobalID ) );
249  ranks = (int*)malloc( nelem[2] * sizeof( int ) );
250  /*
251  * Visible elements info is available for all visible elements, with this call. Similar
252  * information can be retrieved by looping over visible blocks
253  */
254  rc = iMOAB_GetVisibleElementsInfo( pid, &nelem[2], element_global_IDs, ranks, block_IDs );
255  CHECKRC( rc, "failed to get all elem info" );
256  for( i = 0; i < nelem[2]; i++ )
257  printf( " element local id: %3d, global ID: %3d rank:%d block ID: %2d \n", i, element_global_IDs[i],
258  ranks[i], block_IDs[i] );
259  free( element_global_IDs );
260  free( ranks );
261  free( block_IDs );
262 
263  /* Get first element connectivity */
264  nv = 27;
265  eindex = 0;
266  /*
267  * Element connectivity can be retrieved for a single element. Local vertex indices are returned.
268  */
269  rc = iMOAB_GetElementConnectivity( pid, &eindex, &nv, conn );
270  CHECKRC( rc, "failed to get first element connectivity" );
271  printf( " conn for first element: \n" );
272  for( i = 0; i < nv; i++ )
273  printf( " %3d", conn[i] );
274  printf( "\n" );
275 
276  /*
277  * Test neighbors:
278  * Neighbor elements that share a face with current element can be determined with this
279  * call Elements are identified by their local index
280  */
281  rc = iMOAB_GetNeighborElements( pid, &local_index, &num_adjacent_elements, adjacent_element_IDs );
282  CHECKRC( rc, "failed to get first element neighbors" );
283  printf( " neighbors for first element:\n" );
284  for( i = 0; i < num_adjacent_elements; i++ )
285  {
286  printf( " %4d", adjacent_element_IDs[i] );
287  }
288  printf( "\n" );
289 
290  for( i = 0; i < nblocks[2]; i++ )
291  {
292  printf( " block index: %3d, block ID: %3d \n", i, gbIDs[i] );
293  /*
294  * Blocks should have the same type of primary elements. Number of elements in block
295  * and number of vertices per element are found with this call. The method refers
296  * only to the visible elements on the process. The block is identified with its
297  * block ID. Should it be identified with its local index in the list of visible
298  * blocks?
299  */
300  rc = iMOAB_GetBlockInfo( pid, &gbIDs[i], &vertices_per_element, &num_elements_in_block );
301  CHECKRC( rc, "failed to elem block info" );
302  printf( " has %4d elements with %d vertices per element\n", num_elements_in_block,
303  vertices_per_element );
304 
305  size_conn = num_elements_in_block * vertices_per_element;
306  element_connectivity = (iMOAB_LocalID*)malloc( sizeof( iMOAB_LocalID ) * size_conn );
307  /*
308  * Connectivity for all elements in the block can be determined with this method.
309  * Vertices are identified by their local index (from 0 to number of visible
310  * vertices -1)
311  */
312  rc = iMOAB_GetBlockElementConnectivities( pid, &gbIDs[i], &size_conn, element_connectivity );
313  CHECKRC( rc, "failed to get block elem connectivity" );
314  element_ownership = (int*)malloc( sizeof( int ) * num_elements_in_block );
315 
316  /*
317  * Each element is owned by a particular process. Ownership can be returned for all
318  * elements in a block with this call.
319  */
320  rc = iMOAB_GetElementOwnership( pid, &gbIDs[i], &num_elements_in_block, element_ownership );
321  CHECKRC( rc, "failed to get block elem ownership" );
322  global_element_ID = (iMOAB_GlobalID*)malloc( sizeof( iMOAB_GlobalID ) * num_elements_in_block );
323  local_element_ID = (iMOAB_LocalID*)malloc( sizeof( iMOAB_LocalID ) * num_elements_in_block );
324 
325  /*
326  * Global element IDs are determined with this call. Local indices within the
327  * process are returned too.
328  */
329  rc = iMOAB_GetElementID( pid, &gbIDs[i], &num_elements_in_block, global_element_ID, local_element_ID );
330  CHECKRC( rc, "failed to get block elem IDs" );
331  for( j = 0; j < num_elements_in_block; j++ )
332  {
333  printf( " elem %3d owned by %d gid: %4d lid: %4d -- ", j, element_ownership[j],
334  global_element_ID[j], local_element_ID[j] );
335  for( k = 0; k < vertices_per_element; k++ )
336  printf( " %5d", element_connectivity[j * vertices_per_element + k] );
337  printf( "\n" );
338  }
339  free( global_element_ID );
340  free( local_element_ID );
341  free( element_connectivity );
342  free( element_ownership );
343  }
344  /*
345  * Query integer tag values on vertices.
346  * this tag was synchronized (see iMOAB_SynchronizeTags above)
347  * Being a dense tag, all visible vertices have a value.
348  * As usual, the client allocates the returned array, which is filled with data with
349  * this call (deep copy)
350  */
351  int_tag_vals = (int*)malloc( sizeof( int ) * nverts[2] ); /* for all visible vertices on the rank */
352  rc = iMOAB_GetIntTagStorage( pid, "INTFIELD", &nverts[2], &entTypes[0], int_tag_vals );
353  CHECKRC( rc, "failed to get INTFIELD tag" );
354  printf( "INTFIELD tag values:\n" );
355  for( i = 0; i < nverts[2]; i++ )
356  {
357  printf( " %4d", int_tag_vals[i] );
358  if( i % 20 == 19 ) printf( "\n" );
359  }
360  printf( "\n" );
361  free( int_tag_vals );
362 
363  /*
364  * Query double tag values on elements.
365  * This tag was not synchronized, so ghost elements have a default value of 0.
366  */
367  double_tag_vals = (double*)malloc( sizeof( double ) * nelem[2] ); /* for all visible elements on the rank */
368  rc = iMOAB_GetDoubleTagStorage( pid, "DFIELD", &nelem[2], &entTypes[1], double_tag_vals );
369  CHECKRC( rc, "failed to get DFIELD tag" );
370  printf( "DFIELD tag values: (not exchanged) \n" );
371  for( i = 0; i < nelem[2]; i++ )
372  {
373  printf( " %f", double_tag_vals[i] );
374  if( i % 8 == 7 ) printf( "\n" );
375  }
376  printf( "\n" );
377  free( double_tag_vals );
378 
379  /* query surface BCs */
380  surfBC_ID = (iMOAB_LocalID*)malloc( sizeof( iMOAB_LocalID ) * nsbc[2] );
381  ref_surf = (int*)malloc( sizeof( int ) * nsbc[2] );
382  bc_value = (int*)malloc( sizeof( int ) * nsbc[2] );
383  /*
384  * Surface boundary condition information is returned for all visible Neumann conditions
385  * the reference surfaces are indexed from 1 to 6 for hexahedrons, 1 to 4 to
386  * tetrahedrons, in the MOAB canonical ordering convention
387  */
388  rc = iMOAB_GetPointerToSurfaceBC( pid, &nsbc[2], surfBC_ID, ref_surf, bc_value );
389  CHECKRC( rc, "failed to get surf boundary conditions" );
390  printf( " Surface boundary conditions:\n" );
391  for( i = 0; i < nsbc[2]; i++ )
392  {
393  printf( " elem_localID %4d side:%d BC:%2d\n", surfBC_ID[i], ref_surf[i], bc_value[i] );
394  }
395  free( surfBC_ID );
396  free( ref_surf );
397  free( bc_value );
398 
399  /* Query vertex BCs */
400  vertBC_ID = (iMOAB_LocalID*)malloc( sizeof( iMOAB_LocalID ) * ndbc[2] );
401  vertBC_value = (int*)malloc( sizeof( int ) * ndbc[2] );
402  rc = iMOAB_GetPointerToVertexBC( pid, &ndbc[2], vertBC_ID, vertBC_value );
403  CHECKRC( rc, "failed to get vertex boundary conditions" );
404  printf( " Vertex boundary conditions:\n" );
405  for( i = 0; i < ndbc[2]; i++ )
406  {
407  printf( " vertex %4d BC:%2d\n", vertBC_ID[i], vertBC_value[i] );
408  }
409  free( vertBC_ID );
410  free( vertBC_value );
411  }
412 #ifdef MOAB_HAVE_MPI
413  MPI_Barrier( comm ); /* to avoid printing problems */
414 #endif
415  }
416 
417  /* free allocated data */
418  free( coords );
419  free( vGlobalID );
420  free( vranks );
421  outputFile = "fnew.h5m";
422 #ifdef MOAB_HAVE_MPI
423  writeOptions = "PARALLEL=WRITE_PART";
424 #else
425  writeOptions = "";
426 #endif
427  /*
428  * The file can be written in parallel, and it will contain additional tags defined by the user
429  * we may extend the method to write only desired tags to the file
430  */
431  rc = iMOAB_WriteMesh( pid, outputFile, writeOptions );
432  CHECKRC( rc, "failed to write output file" );
433 
434  /*
435  * Deregistering application will delete all mesh entities associated with the application and
436  * will free allocated tag storage.
437  */
438  rc = iMOAB_DeregisterApplication( pid );
439  CHECKRC( rc, "failed to de-register application" );
440 
441  rc = iMOAB_DeregisterApplication( pidDup );
442  CHECKRC( rc, "failed to de-register application" );
443 
444  /*
445  * This method will delete MOAB instance
446  */
447  rc = iMOAB_Finalize();
448  CHECKRC( rc, "failed to finalize MOAB" );
449 #ifdef MOAB_HAVE_MPI
450  MPI_Finalize();
451 #endif
452 
453  return 0;
454 }

References CHECKRC, DENSE_DOUBLE, DENSE_INTEGER, ErrCode, iMOAB_AppID, iMOAB_DefineTagStorage(), iMOAB_DeregisterApplication(), iMOAB_Finalize(), iMOAB_GetBlockElementConnectivities(), iMOAB_GetBlockID(), iMOAB_GetBlockInfo(), iMOAB_GetDoubleTagStorage(), iMOAB_GetElementConnectivity(), iMOAB_GetElementID(), iMOAB_GetElementOwnership(), iMOAB_GetIntTagStorage(), iMOAB_GetMeshInfo(), iMOAB_GetNeighborElements(), iMOAB_GetPointerToSurfaceBC(), iMOAB_GetPointerToVertexBC(), iMOAB_GetVertexID(), iMOAB_GetVertexOwnership(), iMOAB_GetVisibleElementsInfo(), iMOAB_GetVisibleVerticesCoordinates(), iMOAB_GlobalID, iMOAB_Initialize(), iMOAB_LoadMesh(), iMOAB_LocalID, iMOAB_ReadHeaderInfo(), iMOAB_RegisterApplication(), iMOAB_SetGlobalInfo(), iMOAB_SynchronizeTags(), iMOAB_WriteMesh(), MOAB_MESH_DIR, MPI_COMM_WORLD, and rank.