int check_valid_elem_conn( int idx, mhdf_FileHandle file, struct mhdf_FileDesc* desc, int conn_dim ) { long *ranges, *buffer, *iter; int num_ranges; long i, invalid = 0; hid_t handle; mhdf_Status status; const long count = desc->elems[idx].desc.count; const long len = desc->elems[idx].desc.vals_per_ent; ranges = get_dim_ranges( desc, conn_dim, &num_ranges ); handle = mhdf_openConnectivitySimple( file, desc->elems[idx].handle, &status ); if (mhdf_isError(&status)) { fprintf(stderr,"Internal error opening connectivity for %s: %s\n", desc->elems[idx].handle, mhdf_message(&status)); free(ranges); return 1; } buffer = malloc( sizeof(long) * count * len ); mhdf_readConnectivity( handle, 0, count, H5T_NATIVE_LONG, buffer, &status ); if (mhdf_isError(&status)) { fprintf(stderr,"Internal error reading connectivity for %s: %s\n", desc->elems[idx].handle, mhdf_message(&status)); free(ranges); free(buffer); mhdf_closeData( file, handle, &status ); return 1; } mhdf_closeData( file, handle, &status ); iter = buffer; for (i = 0; i < count; ++i, iter += len) { if (!ids_contained( iter, len, ranges, num_ranges)) { if (VERBOSE) printf("Invalid connectivity for element %ld (ID %ld) in %s\n", i, i + desc->elems[idx].desc.start_id, desc->elems[idx].handle ); ++invalid; } } free( buffer ); free( ranges ); if (invalid) { printf("%ld elements with invalid connectivity in %s\n", invalid, desc->elems[idx].handle ); return 1; } return 0; }
int main( int argc, char* argv[] ) { /* input file */ const char* filename; mhdf_FileHandle file; mhdf_Status status; mhdf_Status *const sptr = &status; hid_t handle; /* generic handle used to refer to any data block in file */ /* output file */ const char* gmsh_filename; FILE* gmsh; unsigned gmsh_type; /* hexahedral element type number */ double x, y, z; /* temp storage of node coordinates */ unsigned node_offset, node_id; /* temporary values */ unsigned* connectivity; /* temporary value */ /* node data */ long numnode; /* total number of nodes */ long nodestart; /* file id of first node in list */ int dimension; /* coordinate values per node */ double* nodecoords; /* interleaved node coordinates */ unsigned* nodeids; /* GLOBAL_ID value for nodes */ int have_nodeids = 0; /* hex data */ char* hexgroup = NULL; /* name of element group containing hexes */ long numhex; /* total number of hexahedral elements */ long hexstart; /* file id of first hex in group */ int nodes_per_hex; /* length of connectivity list for a hex */ unsigned* hexconnectivity; /* hex connectivity data */ unsigned* hexids; /* GLOBAL_ID value for hexes */ int have_hexids = 0; /* list of element groups in file */ char** elem_groups; unsigned num_elem_groups; char namebuffer[64]; /* tag data for accessing GLOBAL_ID */ int tagsize; /* number of values for each entity */ int ts, td, tg; /* unused tag properties */ int havesparse, havedense; /* Boolean values */ enum mhdf_TagDataType tagtype; /* base data type of tag */ hid_t sparse_handle[2]; /* handle pair for sparse tag data */ unsigned* sparse_entities; /* temp storage of sparse tag file ids */ unsigned* sparse_ids; /* temp storage of GLOBAL_ID values in spasre tag */ long junk, numtag; /* number of entities for which tag data is available */ long fileid, globalid; /* temporary values */ long ncount = 0, hcount = 0; /* temporary count of number of tag values */ /* iteration */ long i; int j; unsigned k; /* process CL args (expect input .h5m file and output .gmsh file name) */ if (argc != 3) { fprintf(stderr, "Usage: %s <input_file> <output_file>\n", argv[0] ); return 1; } filename = argv[1]; gmsh_filename = argv[2]; /* Open the file */ file = mhdf_openFile( filename, 0, 0, sptr ); CHK_ERR(sptr); /* Read node coordinates. */ handle = mhdf_openNodeCoords( file, &numnode, &dimension, &nodestart, sptr ); CHK_ERR(sptr); nodecoords = (double*)malloc( dimension * numnode * sizeof(double) ); mhdf_readNodeCoords( handle, 0, numnode, nodecoords, sptr ); CHK_ERR(sptr); mhdf_closeData( file, handle, sptr ); CHK_ERR(sptr); /* Find first element group containing hexahedra */ elem_groups = mhdf_getElemHandles( file, &num_elem_groups, sptr ); CHK_ERR(sptr); for (k = 0; k < num_elem_groups; ++k) { mhdf_getElemTypeName( file, elem_groups[k], namebuffer, sizeof(namebuffer), sptr ); CHK_ERR(sptr); if (!hexgroup && !strcmp(mdhf_HEX_TYPE_NAME, namebuffer)) hexgroup = strdup(elem_groups[k]); else printf( "Skipping element group '%s' containing element of type '%s'\n", elem_groups[k], namebuffer ); } free( elem_groups ); if (!hexgroup) { fprintf( stderr, "No Hexahedra defined in file\n" ); return 4; } /* Read Hexahedron connectivity */ handle = mhdf_openConnectivity( file, hexgroup, &nodes_per_hex, &numhex, &hexstart, sptr ); CHK_ERR(sptr); hexconnectivity = (unsigned*)malloc(numhex * nodes_per_hex * sizeof(unsigned)); mhdf_readConnectivity( handle, 0, numhex, H5T_NATIVE_UINT, hexconnectivity, sptr ); CHK_ERR(sptr); mhdf_closeData( file, handle, sptr ); CHK_ERR(sptr); /* Note: hex connectivity list contains file-space node IDs, which are the nodes in the sequence they are read from the file, with the first node having an ID of 'nodestart' */ /* Check for "GLOBAL_ID" tag */ nodeids = (unsigned*)malloc( numnode * sizeof(unsigned) ); hexids = (unsigned*)malloc( numhex * sizeof(unsigned) ); mhdf_getTagInfo( file, "GLOBAL_ID", &tagtype, &tagsize, &ts, &td, &tg, &havesparse, sptr ); /* If have GLOBAL_ID tag, try to read values for nodes and hexes */ if (!mhdf_isError(sptr)) { /* Check that the tag contains what we expect */ if (tagtype != mhdf_INTEGER || tagsize != 1) { fprintf(stderr, "ERROR: Invalid data type for 'GLOBAL_ID' tag.\n"); exit(3); } /* Check for and read dense-format tag data for nodes */ havedense = mhdf_haveDenseTag( file, "GLOBAL_ID", mhdf_node_type_handle(), sptr ); CHK_ERR(sptr); if (havedense) { handle = mhdf_openDenseTagData( file, "GLOBAL_ID", mhdf_node_type_handle(), &numtag, sptr ); CHK_ERR(sptr); assert( numtag == numnode ); mhdf_readDenseTag( handle, 0, numtag, H5T_NATIVE_UINT, nodeids, sptr ); CHK_ERR(sptr); mhdf_closeData( file, handle, sptr ); CHK_ERR(sptr); have_nodeids = 1; } /* Check for and read dense-format tag data for hexes */ havedense = mhdf_haveDenseTag( file, "GLOBAL_ID", hexgroup, sptr ); CHK_ERR(sptr); if (havedense) { handle = mhdf_openDenseTagData( file, "GLOBAL_ID", hexgroup, &numtag, sptr ); CHK_ERR(sptr); assert( numtag == numhex ); mhdf_readDenseTag( handle, 0, numtag, H5T_NATIVE_UINT, hexids, sptr ); CHK_ERR(sptr); mhdf_closeData( file, handle, sptr ); CHK_ERR(sptr); have_hexids = 1; } /* Check for and read sparse-format tag data */ if (havesparse) { mhdf_openSparseTagData( file, "GLOBAL_ID", &numtag, &junk, sparse_handle, sptr ); CHK_ERR(sptr); sparse_entities = (unsigned*)malloc(numtag * sizeof(unsigned)); mhdf_readSparseTagEntities( sparse_handle[0], 0, numtag, H5T_NATIVE_UINT, sparse_entities, sptr ); CHK_ERR(sptr); sparse_ids = (unsigned*)malloc(numtag * sizeof(unsigned)); mhdf_readSparseTagValues( sparse_handle[1], 0, numtag, H5T_NATIVE_UINT, sparse_ids, sptr ); CHK_ERR(sptr); mhdf_closeData( file, sparse_handle[0], sptr ); CHK_ERR(sptr); mhdf_closeData( file, sparse_handle[1], sptr ); CHK_ERR(sptr); /* Set hex and node ids from sparse tag data */ for (i = 0; i < numtag; ++i) { fileid = sparse_entities[i]; globalid = sparse_ids[i]; if (fileid >= nodestart && fileid - nodestart < numnode) { nodeids[fileid - nodestart] = globalid; ++ncount; } else if (fileid >= hexstart && fileid - hexstart < numhex) { hexids[fileid - hexstart] = globalid; ++hcount; } } free( sparse_ids ); free( sparse_entities ); /* make sure there was an ID for each node and each hex */ if (ncount == numnode) have_nodeids = 1; if (hcount == numhex) have_hexids = 1; } /* end have sparse tag for GLOBAL_ID */ } /* end have GLOBAL_ID tag */ /* done with input file */ free( hexgroup ); mhdf_closeFile( file, sptr ); CHK_ERR(sptr); /* if no GLOBAL_ID, just use incrementing values */ if (!have_nodeids) for (i = 0; i < numnode; ++i) nodeids[i] = i+1; if (!have_hexids) for (i = 0; i < numhex; ++i) hexids[i] = i+1; /* write out as gmesh file version 1.0 */ /* get gmsh type for hexahedrons */ if (nodes_per_hex == 8) gmsh_type = 5; else if (nodes_per_hex == 27) gmsh_type = 12; else { fprintf(stderr, "Cannot store %d node hex in gmsh file.\n", nodes_per_hex); exit(4); } /* open file */ gmsh = fopen( gmsh_filename, "w" ); /* Write node data. If dimension is less than 3, write zero for other coordinate values. In the (highly unlikely) case that dimension is greater than three, disregard higher-dimension coordinate values. */ fprintf(gmsh, "$NOD\n" ); fprintf(gmsh, "%lu\n", numnode ); for (i = 0; i < numnode; ++i) { x = nodecoords[dimension*i]; y = z = 0.0; if (dimension > 1) { y = nodecoords[dimension*i+1]; if (dimension > 2) { z = nodecoords[dimension*i+2]; } } fprintf(gmsh, "%u %f %f %f\n", nodeids[i], x, y, z ); } /* Write element connectivity data */ fprintf(gmsh, "$ENDNOD\n$ELM\n" ); fprintf(gmsh, "%lu\n", numhex ); for (i = 0; i < numhex; ++i) { fprintf( gmsh, "%u %u 1 1 %d", hexids[i], gmsh_type, nodes_per_hex ); /* connectivity list for this hex */ connectivity = hexconnectivity + i*nodes_per_hex; for (j = 0; j < nodes_per_hex; ++j) { /* get offset in node list from file id */ node_offset = connectivity[j] - nodestart; /* get node id from ID list */ node_id = nodeids[node_offset]; fprintf( gmsh, " %u", node_id ); } fprintf( gmsh, "\n" ); } fprintf( gmsh, "$ENDELM\n" ); fclose( gmsh ); return 0; }