iMOAB
driver.c
Go to the documentation of this file.
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 }
 All Files Functions Enumerations Enumerator Defines