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