MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 #include "moab/MOABConfig.h" 00002 00003 #ifdef MOAB_HAVE_MPI 00004 #include "moab_mpi.h" 00005 #endif 00006 00007 #include "moab/iMOAB.h" 00008 #include <string.h> 00009 00010 #define CHECKRC( rc, message ) \ 00011 if( 0 != ( rc ) ) \ 00012 { \ 00013 printf( "Error: %s.\n", message ); \ 00014 return 1; \ 00015 } 00016 00017 int main( int argc, char* argv[] ) 00018 { 00019 /* Declarations */ 00020 ErrCode rc; 00021 int nprocs = 1, rank = 0; 00022 char filen[1024] = ""; 00023 int i, j, k; 00024 00025 int irank = 0, num_tags_to_sync = 1; 00026 int* ranks; 00027 00028 int appID, appDupID; 00029 iMOAB_AppID pid; 00030 iMOAB_AppID pidDup; 00031 int compid = 11, compdupid = 12; 00032 00033 int num_global_vertices = 0, num_global_elements = 0, num_dimension = 0, num_parts = 0; 00034 int nverts[3], nelem[3], nblocks[3], nsbc[3], ndbc[3]; 00035 00036 iMOAB_GlobalID* vGlobalID; 00037 int* vranks; 00038 double* coords; 00039 int size_coords; 00040 00041 #ifdef MOAB_HAVE_MPI 00042 const char* read_opts = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS"; 00043 int num_ghost_layers[1] = { 1 }; 00044 #else 00045 const char* read_opts = ""; 00046 int num_ghost_layers[1] = { 0 }; 00047 #endif 00048 00049 iMOAB_GlobalID* gbIDs; 00050 int tagIndex[2]; 00051 int entTypes[2] = { 0, 1 }; /* first is on vertex, second is on elements; */ 00052 int tagTypes[2] = { DENSE_INTEGER, DENSE_DOUBLE }; 00053 int num_components = 1; 00054 00055 iMOAB_GlobalID *element_global_IDs, *block_IDs; 00056 int vertices_per_element, num_elements_in_block; 00057 int conn[27], nv, eindex; 00058 00059 int* int_tag_vals; 00060 double* double_tag_vals; 00061 00062 int local_index = 0; /* test element with local index 0 */ 00063 int num_adjacent_elements = 10; /* we can have maximum 6 actually */ 00064 iMOAB_LocalID adjacent_element_IDs[10], *element_connectivity, *local_element_ID; 00065 int size_conn, *element_ownership; 00066 iMOAB_GlobalID* global_element_ID; 00067 00068 iMOAB_LocalID *vertBC_ID, *surfBC_ID; 00069 int *vertBC_value, *ref_surf, *bc_value; 00070 00071 char *outputFile, *writeOptions; 00072 00073 #ifdef MOAB_HAVE_MPI 00074 MPI_Comm comm; 00075 MPI_Init( &argc, &argv ); 00076 00077 comm = MPI_COMM_WORLD; 00078 MPI_Comm_size( comm, &nprocs ); 00079 MPI_Comm_rank( comm, &rank ); 00080 #endif 00081 00082 #ifdef MOAB_HAVE_HDF5 00083 strcpy( filen, MOAB_MESH_DIR ); 00084 strcat( filen, "unittest/io/p8ex1.h5m" ); 00085 #endif 00086 00087 if( argc > 1 ) strcpy( filen, argv[1] ); 00088 00089 if( !strlen( filen ) ) 00090 { 00091 printf( "Invalid filename specified at command line.\n" ); 00092 return 1; 00093 } 00094 /* 00095 * MOAB needs to be initialized; A MOAB instance will be created, and will be used by each 00096 * application in this framework. There is no parallel context yet. 00097 */ 00098 rc = iMOAB_Initialize( argc, argv ); 00099 CHECKRC( rc, "failed to initialize MOAB" ); 00100 00101 /* 00102 * Header information is cheap to retrieve from an hdf5 file; it can be called by each process 00103 * or can be called by one master task and broadcasted. The hdf5 file has to be in MOAB native 00104 * format, and has to be partitioned in advance. There should be at least as many partitions in 00105 * the file as number of tasks in the communicator. 00106 */ 00107 rc = iMOAB_ReadHeaderInfo( filen, &num_global_vertices, &num_global_elements, &num_dimension, &num_parts ); 00108 CHECKRC( rc, "failed to read header info" ); 00109 00110 if( 0 == rank ) 00111 { 00112 printf( "file %s has %d vertices, %d elements, %d parts in partition\n", filen, num_global_vertices, 00113 num_global_elements, num_parts ); 00114 } 00115 00116 pid = &appID; 00117 pidDup = &appDupID; 00118 00119 /* 00120 * Each application has to be registered once. A mesh set and a parallel communicator will be 00121 * associated with each application. A unique application id will be returned, and will be used 00122 * for all future mesh operations/queries. 00123 */ 00124 rc = iMOAB_RegisterApplication( "MBAPP", 00125 #ifdef MOAB_HAVE_MPI 00126 &comm, 00127 #endif 00128 &compid, pid ); 00129 CHECKRC( rc, "failed to register application" ); 00130 00131 rc = iMOAB_RegisterApplication( "MBDUPAPP", 00132 #ifdef MOAB_HAVE_MPI 00133 &comm, 00134 #endif 00135 &compdupid, pidDup ); 00136 CHECKRC( rc, "failed to register duplicate application" ); 00137 00138 /* 00139 * Loading the mesh is a parallel IO operation. Ghost layers can be exchanged too, and default 00140 * MOAB sets are augmented with ghost elements. By convention, blocks correspond to MATERIAL_SET 00141 * sets, side sets with NEUMANN_SET sets, node sets with DIRICHLET_SET sets. Each element and 00142 * vertex entity should have a GLOBAL ID tag in the file, which will be available for visible 00143 * entities 00144 */ 00145 rc = iMOAB_LoadMesh( pid, filen, read_opts, num_ghost_layers ); 00146 CHECKRC( rc, "failed to load mesh" ); 00147 00148 rc = iMOAB_LoadMesh( pidDup, filen, read_opts, num_ghost_layers ); 00149 CHECKRC( rc, "failed to load mesh" ); 00150 00151 rc = iMOAB_SetGlobalInfo( pid, &num_global_vertices, &num_global_elements ); 00152 CHECKRC( rc, "failed to set global info" ); 00153 00154 /* 00155 * Each process in the communicator will have access to a local mesh instance, which will 00156 * contain the original cells in the local partition and ghost entities. Number of vertices, 00157 * primary cells, visible blocks, number of sidesets and nodesets boundary conditions will be 00158 * returned in size 3 arrays, for local, ghost and total numbers. 00159 */ 00160 rc = iMOAB_GetMeshInfo( pid, nverts, nelem, nblocks, nsbc, ndbc ); 00161 CHECKRC( rc, "failed to get mesh info" ); 00162 00163 vGlobalID = (iMOAB_GlobalID*)malloc( nverts[2] * sizeof( iMOAB_GlobalID ) ); 00164 /* 00165 * All visible vertices have a unique global ID. All arrays are allocated by client. 00166 * Currently, global ID is a 32 bit integer, total number of visible vertices was returned by 00167 * iMOAB_GetMeshInfo 00168 */ 00169 rc = iMOAB_GetVertexID( pid, &nverts[2], vGlobalID ); 00170 CHECKRC( rc, "failed to get vertex id info" ); 00171 00172 vranks = (int*)malloc( nverts[2] * sizeof( int ) ); 00173 /* 00174 * In MOAB terminology, a vertex can be owned, shared or ghost. An owned vertex will be 00175 * owned by the current process. A shared vertex appears at the interface between partitions, it 00176 * can be owned by another process, while a ghost vertex is owned by another process always. All 00177 * vertex arrays have a natural local order, in which the ghost vertices are at the end of the 00178 * arrays. The local index of the vertex will vary from 0 to number of visible vertices (in this 00179 * example nverts[2]-1) 00180 */ 00181 rc = iMOAB_GetVertexOwnership( pid, &nverts[2], vranks ); 00182 CHECKRC( rc, "failed to get vertex ranks" ); 00183 00184 coords = (double*)malloc( 3 * nverts[2] * sizeof( double ) ); 00185 size_coords = 3 * nverts[2]; 00186 /* 00187 * Coordinates are returned interleaved, for all visible vertices. Size is dimension times 00188 * number of visible vertices 00189 */ 00190 rc = iMOAB_GetVisibleVerticesCoordinates( pid, &size_coords, coords ); 00191 CHECKRC( rc, "failed to get coordinates" ); 00192 00193 /* 00194 * Block IDs correspond to MATERIAL_SET tag values in hdf5 file 00195 * They also correspond to block IDs in a Cubit model. 00196 * Local visible blocks might contain ghost cells, owned by other 00197 * processes. 00198 * 00199 * Inside MOAB, a block will correspond to a meshset with a MATERIAL_SET tag, 00200 * with value the block ID. 00201 * A MATERIAL_SET tag in moab if SPARSE and type INTEGER. 00202 */ 00203 gbIDs = (iMOAB_GlobalID*)malloc( nblocks[2] * sizeof( iMOAB_GlobalID ) ); 00204 rc = iMOAB_GetBlockID( pid, &nblocks[2], gbIDs ); 00205 CHECKRC( rc, "failed to get block info" ); 00206 00207 /* 00208 * The 2 tags used in this example exist in the file, already. 00209 * If a user needs a new tag, it can be defined with the same call as this one 00210 * this method, iMOAB_DefineTagStorage, will return a local index for the tag. 00211 * The name of the tag is case sensitive. 00212 * This method is collective. 00213 */ 00214 rc = iMOAB_DefineTagStorage( pid, "INTFIELD", &tagTypes[0], &num_components, &tagIndex[0] ); 00215 CHECKRC( rc, "failed to get tag INTFIELD " ); 00216 rc = iMOAB_DefineTagStorage( pid, "DFIELD", &tagTypes[1], &num_components, &tagIndex[1] ); 00217 CHECKRC( rc, "failed to get tag DFIELD " ); 00218 00219 /* 00220 * Synchronize one of the tags only, just to see what happens; 00221 * Tags are not exchanged for ghost entities by default. The user has to explicitly 00222 * synchronize them with a call like this one. The tags to synchronize are referenced by the 00223 * index returned at their "definition" with iMOAB_DefineTagStorage method. 00224 */ 00225 rc = iMOAB_SynchronizeTags( pid, &num_tags_to_sync, &tagIndex[0], &tagTypes[0] ); 00226 CHECKRC( rc, "failed to sync tag INTFIELD " ); 00227 00228 for( irank = 0; irank < nprocs; irank++ ) 00229 { 00230 if( irank == rank ) 00231 { 00232 /* printf some of the block info */ 00233 printf( "on rank %d, there are \n" 00234 " %3d visible vertices of which %3d local %3d ghost \n" 00235 " %3d visible elements of which %3d owned %3d ghost \n" 00236 " %3d visible blocks\n" 00237 " %3d visible neumann BCs\n" 00238 " %3d visible dirichlet BCs\n", 00239 rank, nverts[2], nverts[0], nverts[1], nelem[2], nelem[0], nelem[1], nblocks[2], nsbc[2], ndbc[2] ); 00240 00241 /* print some of the vertex id infos */ 00242 printf( "on rank %d vertex info:\n", rank ); 00243 for( i = 0; i < nverts[2]; i++ ) 00244 printf( " vertex local id: %3d, rank ID:%d global ID: %3d coords: %g, %g, %g\n", i, vranks[i], 00245 vGlobalID[i], coords[3 * i], coords[3 * i + 1], coords[3 * i + 2] ); 00246 00247 element_global_IDs = (iMOAB_GlobalID*)malloc( nelem[2] * sizeof( iMOAB_GlobalID ) ); 00248 block_IDs = (iMOAB_GlobalID*)malloc( nelem[2] * sizeof( iMOAB_GlobalID ) ); 00249 ranks = (int*)malloc( nelem[2] * sizeof( int ) ); 00250 /* 00251 * Visible elements info is available for all visible elements, with this call. Similar 00252 * information can be retrieved by looping over visible blocks 00253 */ 00254 rc = iMOAB_GetVisibleElementsInfo( pid, &nelem[2], element_global_IDs, ranks, block_IDs ); 00255 CHECKRC( rc, "failed to get all elem info" ); 00256 for( i = 0; i < nelem[2]; i++ ) 00257 printf( " element local id: %3d, global ID: %3d rank:%d block ID: %2d \n", i, element_global_IDs[i], 00258 ranks[i], block_IDs[i] ); 00259 free( element_global_IDs ); 00260 free( ranks ); 00261 free( block_IDs ); 00262 00263 /* Get first element connectivity */ 00264 nv = 27; 00265 eindex = 0; 00266 /* 00267 * Element connectivity can be retrieved for a single element. Local vertex indices are returned. 00268 */ 00269 rc = iMOAB_GetElementConnectivity( pid, &eindex, &nv, conn ); 00270 CHECKRC( rc, "failed to get first element connectivity" ); 00271 printf( " conn for first element: \n" ); 00272 for( i = 0; i < nv; i++ ) 00273 printf( " %3d", conn[i] ); 00274 printf( "\n" ); 00275 00276 /* 00277 * Test neighbors: 00278 * Neighbor elements that share a face with current element can be determined with this 00279 * call Elements are identified by their local index 00280 */ 00281 rc = iMOAB_GetNeighborElements( pid, &local_index, &num_adjacent_elements, adjacent_element_IDs ); 00282 CHECKRC( rc, "failed to get first element neighbors" ); 00283 printf( " neighbors for first element:\n" ); 00284 for( i = 0; i < num_adjacent_elements; i++ ) 00285 { 00286 printf( " %4d", adjacent_element_IDs[i] ); 00287 } 00288 printf( "\n" ); 00289 00290 for( i = 0; i < nblocks[2]; i++ ) 00291 { 00292 printf( " block index: %3d, block ID: %3d \n", i, gbIDs[i] ); 00293 /* 00294 * Blocks should have the same type of primary elements. Number of elements in block 00295 * and number of vertices per element are found with this call. The method refers 00296 * only to the visible elements on the process. The block is identified with its 00297 * block ID. Should it be identified with its local index in the list of visible 00298 * blocks? 00299 */ 00300 rc = iMOAB_GetBlockInfo( pid, &gbIDs[i], &vertices_per_element, &num_elements_in_block ); 00301 CHECKRC( rc, "failed to elem block info" ); 00302 printf( " has %4d elements with %d vertices per element\n", num_elements_in_block, 00303 vertices_per_element ); 00304 00305 size_conn = num_elements_in_block * vertices_per_element; 00306 element_connectivity = (iMOAB_LocalID*)malloc( sizeof( iMOAB_LocalID ) * size_conn ); 00307 /* 00308 * Connectivity for all elements in the block can be determined with this method. 00309 * Vertices are identified by their local index (from 0 to number of visible 00310 * vertices -1) 00311 */ 00312 rc = iMOAB_GetBlockElementConnectivities( pid, &gbIDs[i], &size_conn, element_connectivity ); 00313 CHECKRC( rc, "failed to get block elem connectivity" ); 00314 element_ownership = (int*)malloc( sizeof( int ) * num_elements_in_block ); 00315 00316 /* 00317 * Each element is owned by a particular process. Ownership can be returned for all 00318 * elements in a block with this call. 00319 */ 00320 rc = iMOAB_GetElementOwnership( pid, &gbIDs[i], &num_elements_in_block, element_ownership ); 00321 CHECKRC( rc, "failed to get block elem ownership" ); 00322 global_element_ID = (iMOAB_GlobalID*)malloc( sizeof( iMOAB_GlobalID ) * num_elements_in_block ); 00323 local_element_ID = (iMOAB_LocalID*)malloc( sizeof( iMOAB_LocalID ) * num_elements_in_block ); 00324 00325 /* 00326 * Global element IDs are determined with this call. Local indices within the 00327 * process are returned too. 00328 */ 00329 rc = iMOAB_GetElementID( pid, &gbIDs[i], &num_elements_in_block, global_element_ID, local_element_ID ); 00330 CHECKRC( rc, "failed to get block elem IDs" ); 00331 for( j = 0; j < num_elements_in_block; j++ ) 00332 { 00333 printf( " elem %3d owned by %d gid: %4d lid: %4d -- ", j, element_ownership[j], 00334 global_element_ID[j], local_element_ID[j] ); 00335 for( k = 0; k < vertices_per_element; k++ ) 00336 printf( " %5d", element_connectivity[j * vertices_per_element + k] ); 00337 printf( "\n" ); 00338 } 00339 free( global_element_ID ); 00340 free( local_element_ID ); 00341 free( element_connectivity ); 00342 free( element_ownership ); 00343 } 00344 /* 00345 * Query integer tag values on vertices. 00346 * this tag was synchronized (see iMOAB_SynchronizeTags above) 00347 * Being a dense tag, all visible vertices have a value. 00348 * As usual, the client allocates the returned array, which is filled with data with 00349 * this call (deep copy) 00350 */ 00351 int_tag_vals = (int*)malloc( sizeof( int ) * nverts[2] ); /* for all visible vertices on the rank */ 00352 rc = iMOAB_GetIntTagStorage( pid, "INTFIELD", &nverts[2], &entTypes[0], int_tag_vals ); 00353 CHECKRC( rc, "failed to get INTFIELD tag" ); 00354 printf( "INTFIELD tag values:\n" ); 00355 for( i = 0; i < nverts[2]; i++ ) 00356 { 00357 printf( " %4d", int_tag_vals[i] ); 00358 if( i % 20 == 19 ) printf( "\n" ); 00359 } 00360 printf( "\n" ); 00361 free( int_tag_vals ); 00362 00363 /* 00364 * Query double tag values on elements. 00365 * This tag was not synchronized, so ghost elements have a default value of 0. 00366 */ 00367 double_tag_vals = (double*)malloc( sizeof( double ) * nelem[2] ); /* for all visible elements on the rank */ 00368 rc = iMOAB_GetDoubleTagStorage( pid, "DFIELD", &nelem[2], &entTypes[1], double_tag_vals ); 00369 CHECKRC( rc, "failed to get DFIELD tag" ); 00370 printf( "DFIELD tag values: (not exchanged) \n" ); 00371 for( i = 0; i < nelem[2]; i++ ) 00372 { 00373 printf( " %f", double_tag_vals[i] ); 00374 if( i % 8 == 7 ) printf( "\n" ); 00375 } 00376 printf( "\n" ); 00377 free( double_tag_vals ); 00378 00379 /* query surface BCs */ 00380 surfBC_ID = (iMOAB_LocalID*)malloc( sizeof( iMOAB_LocalID ) * nsbc[2] ); 00381 ref_surf = (int*)malloc( sizeof( int ) * nsbc[2] ); 00382 bc_value = (int*)malloc( sizeof( int ) * nsbc[2] ); 00383 /* 00384 * Surface boundary condition information is returned for all visible Neumann conditions 00385 * the reference surfaces are indexed from 1 to 6 for hexahedrons, 1 to 4 to 00386 * tetrahedrons, in the MOAB canonical ordering convention 00387 */ 00388 rc = iMOAB_GetPointerToSurfaceBC( pid, &nsbc[2], surfBC_ID, ref_surf, bc_value ); 00389 CHECKRC( rc, "failed to get surf boundary conditions" ); 00390 printf( " Surface boundary conditions:\n" ); 00391 for( i = 0; i < nsbc[2]; i++ ) 00392 { 00393 printf( " elem_localID %4d side:%d BC:%2d\n", surfBC_ID[i], ref_surf[i], bc_value[i] ); 00394 } 00395 free( surfBC_ID ); 00396 free( ref_surf ); 00397 free( bc_value ); 00398 00399 /* Query vertex BCs */ 00400 vertBC_ID = (iMOAB_LocalID*)malloc( sizeof( iMOAB_LocalID ) * ndbc[2] ); 00401 vertBC_value = (int*)malloc( sizeof( int ) * ndbc[2] ); 00402 rc = iMOAB_GetPointerToVertexBC( pid, &ndbc[2], vertBC_ID, vertBC_value ); 00403 CHECKRC( rc, "failed to get vertex boundary conditions" ); 00404 printf( " Vertex boundary conditions:\n" ); 00405 for( i = 0; i < ndbc[2]; i++ ) 00406 { 00407 printf( " vertex %4d BC:%2d\n", vertBC_ID[i], vertBC_value[i] ); 00408 } 00409 free( vertBC_ID ); 00410 free( vertBC_value ); 00411 } 00412 #ifdef MOAB_HAVE_MPI 00413 MPI_Barrier( comm ); /* to avoid printing problems */ 00414 #endif 00415 } 00416 00417 /* free allocated data */ 00418 free( coords ); 00419 free( vGlobalID ); 00420 free( vranks ); 00421 outputFile = "fnew.h5m"; 00422 #ifdef MOAB_HAVE_MPI 00423 writeOptions = "PARALLEL=WRITE_PART"; 00424 #else 00425 writeOptions = ""; 00426 #endif 00427 /* 00428 * The file can be written in parallel, and it will contain additional tags defined by the user 00429 * we may extend the method to write only desired tags to the file 00430 */ 00431 rc = iMOAB_WriteMesh( pid, outputFile, writeOptions ); 00432 CHECKRC( rc, "failed to write output file" ); 00433 00434 /* 00435 * Deregistering application will delete all mesh entities associated with the application and 00436 * will free allocated tag storage. 00437 */ 00438 rc = iMOAB_DeregisterApplication( pid ); 00439 CHECKRC( rc, "failed to de-register application" ); 00440 00441 rc = iMOAB_DeregisterApplication( pidDup ); 00442 CHECKRC( rc, "failed to de-register application" ); 00443 00444 /* 00445 * This method will delete MOAB instance 00446 */ 00447 rc = iMOAB_Finalize(); 00448 CHECKRC( rc, "failed to finalize MOAB" ); 00449 #ifdef MOAB_HAVE_MPI 00450 MPI_Finalize(); 00451 #endif 00452 00453 return 0; 00454 }