MOAB: Mesh Oriented datABase  (version 5.2.1)
hexes_to_gmsh.c
Go to the documentation of this file.
00001 /**
00002  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
00003  * storing and accessing finite element mesh data.
00004  *
00005  * Copyright 2006 Sandia Corporation.  Under the terms of Contract
00006  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00007  * retains certain rights in this software.
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  */
00015 
00016 /* Example file for using mhdf interface for reading MOAB native file foramt
00017  *
00018  * Requires libmhdf from MOAB source and HDF5 library
00019  *
00020  * Reads:
00021  *  - all node coordinates
00022  *  - a single group of hexahedral elements
00023  *  - GLOBAL_ID tag if present
00024  * and writes as Gmsh file version 1.0.
00025  *
00026  * Does not contain examples for reading meshsets or
00027  * reading polygon or polyhedron elements.
00028  *
00029  * A simple exorcise:
00030  *    Clean up handling of variable number of dimensions by reading
00031  *    node coordinate data one dimension at a time using
00032  *    mhdf_readNodeCoord
00033  *
00034  * A more complex exorcise:
00035  *    Read meshsets with MATERIAL_SET tag, which MOAB uses to
00036  *    represent element blocks, and assign appropriate element
00037  *    block for each hex in Gmsh file.
00038  *    Hint: look for and read MATERIAL_SET tag first to get list of entities
00039  *          then read set contents for sets with that tag
00040  *          then match hex file ids to lists of set contents
00041  *    Be careful of the mhdf_SET_RANGE_BIT for each set when reading set
00042  *    contents.
00043  */
00044 
00045 #include <stdlib.h>
00046 #include <stdio.h>
00047 #include <assert.h>
00048 #include <string.h>
00049 
00050 /* mhdf API */
00051 #include "mhdf.h"
00052 /* need constants for native types (e.g. H5T_NATIVE_UINT)*/
00053 #include <H5Tpublic.h>
00054 
00055 /* Macro to check return status from mhdf calls.  Exit on error. */
00056 #define CHK_ERR( A )                                             \
00057     do                                                           \
00058     {                                                            \
00059         if( mhdf_isError( A ) )                                  \
00060         {                                                        \
00061             fprintf( stderr, "Error: %s\n", mhdf_message( A ) ); \
00062             exit( 2 );                                           \
00063         }                                                        \
00064     } while( 0 )
00065 
00066 int main( int argc, char* argv[] )
00067 {
00068     /* input file */
00069     const char*        filename;
00070     mhdf_FileHandle    file;
00071     mhdf_Status        status;
00072     mhdf_Status* const sptr = &status;
00073     hid_t              handle; /* generic handle used to refer to any data block in file */
00074 
00075     /* output file */
00076     const char* gmsh_filename;
00077     FILE*       gmsh;
00078     unsigned    gmsh_type; /* hexahedral element type number */
00079     double      x, y, z; /* temp storage of node coordinates */
00080     unsigned    node_offset, node_id; /* temporary values */
00081     unsigned*   connectivity; /* temporary value */
00082 
00083     /* node data */
00084     long      numnode; /* total number of nodes */
00085     long      nodestart; /* file id of first node in list */
00086     int       dimension; /* coordinate values per node */
00087     double*   nodecoords; /* interleaved node coordinates */
00088     unsigned* nodeids; /* GLOBAL_ID value for nodes */
00089     int       have_nodeids = 0;
00090 
00091     /* hex data */
00092     char*     hexgroup = NULL; /* name of element group containing hexes */
00093     long      numhex; /* total number of hexahedral elements */
00094     long      hexstart; /* file id of first hex in group */
00095     int       nodes_per_hex; /* length of connectivity list for a hex */
00096     unsigned* hexconnectivity; /* hex connectivity data */
00097     unsigned* hexids; /* GLOBAL_ID value for hexes */
00098     int       have_hexids = 0;
00099 
00100     /* list of element groups in file */
00101     char**   elem_groups;
00102     unsigned num_elem_groups;
00103     char     namebuffer[ 64 ];
00104 
00105     /* tag data for accessing GLOBAL_ID */
00106     int                   tagsize; /* number of values for each entity */
00107     int                   ts, td, tg; /* unused tag properties */
00108     int                   havesparse, havedense; /* Boolean values */
00109     enum mhdf_TagDataType tagtype; /* base data type of tag */
00110     hid_t                 sparse_handle[ 2 ]; /* handle pair for sparse tag data */
00111     unsigned*             sparse_entities; /* temp storage of sparse tag file ids */
00112     unsigned*             sparse_ids; /* temp storage of GLOBAL_ID values in spasre tag */
00113     long                  junk, numtag; /* number of entities for which tag data is available */
00114     long                  fileid, globalid; /* temporary values */
00115     long                  ncount = 0, hcount = 0; /* temporary count of number of tag values */
00116 
00117     /* iteration */
00118     long     i;
00119     int      j;
00120     unsigned k;
00121 
00122     /* process CL args (expect input .h5m file and output .gmsh file name) */
00123     if( argc != 3 )
00124     {
00125         fprintf( stderr, "Usage: %s <input_file> <output_file>\n", argv[ 0 ] );
00126         return 1;
00127     }
00128     filename = argv[ 1 ];
00129     gmsh_filename = argv[ 2 ];
00130 
00131     /* Open the file */
00132     file = mhdf_openFile( filename, 0, 0, sptr );CHK_ERR( sptr );
00133 
00134     /* Read node coordinates. */
00135     handle = mhdf_openNodeCoords( file, &numnode, &dimension, &nodestart, sptr );CHK_ERR( sptr );
00136     nodecoords = (double*)malloc( dimension * numnode * sizeof( double ) );
00137     mhdf_readNodeCoords( handle, 0, numnode, nodecoords, sptr );CHK_ERR( sptr );
00138     mhdf_closeData( file, handle, sptr );CHK_ERR( sptr );
00139 
00140     /* Find first element group containing hexahedra */
00141     elem_groups = mhdf_getElemHandles( file, &num_elem_groups, sptr );CHK_ERR( sptr );
00142     for( k = 0; k < num_elem_groups; ++k )
00143     {
00144         mhdf_getElemTypeName( file, elem_groups[ k ], namebuffer, sizeof( namebuffer ), sptr );CHK_ERR( sptr );
00145         if( !hexgroup && !strcmp( mdhf_HEX_TYPE_NAME, namebuffer ) )
00146             hexgroup = strdup( elem_groups[ k ] );
00147         else
00148             printf( "Skipping element group '%s' containing element of type '%s'\n", elem_groups[ k ], namebuffer );
00149     }
00150     free( elem_groups );
00151 
00152     if( !hexgroup )
00153     {
00154         fprintf( stderr, "No Hexahedra defined in file\n" );
00155         return 4;
00156     }
00157 
00158     /* Read Hexahedron connectivity */
00159     handle = mhdf_openConnectivity( file, hexgroup, &nodes_per_hex, &numhex, &hexstart, sptr );CHK_ERR( sptr );
00160     hexconnectivity = (unsigned*)malloc( numhex * nodes_per_hex * sizeof( unsigned ) );
00161     mhdf_readConnectivity( handle, 0, numhex, H5T_NATIVE_UINT, hexconnectivity, sptr );CHK_ERR( sptr );
00162     mhdf_closeData( file, handle, sptr );CHK_ERR( sptr );
00163     /* Note: hex connectivity list contains file-space node IDs, which are
00164              the nodes in the sequence they are read from the file, with
00165              the first node having an ID of 'nodestart' */
00166 
00167     /* Check for "GLOBAL_ID" tag */
00168     nodeids = (unsigned*)malloc( numnode * sizeof( unsigned ) );
00169     hexids = (unsigned*)malloc( numhex * sizeof( unsigned ) );
00170     mhdf_getTagInfo( file, "GLOBAL_ID", &tagtype, &tagsize, &ts, &td, &tg, &havesparse, sptr );
00171 
00172     /* If have GLOBAL_ID tag, try to read values for nodes and hexes */
00173     if( !mhdf_isError( sptr ) )
00174     {
00175         /* Check that the tag contains what we expect */
00176         if( tagtype != mhdf_INTEGER || tagsize != 1 )
00177         {
00178             fprintf( stderr, "ERROR: Invalid data type for 'GLOBAL_ID' tag.\n" );
00179             exit( 3 );
00180         }
00181 
00182         /* Check for and read dense-format tag data for nodes */
00183         havedense = mhdf_haveDenseTag( file, "GLOBAL_ID", mhdf_node_type_handle( ), sptr );CHK_ERR( sptr );
00184         if( havedense )
00185         {
00186             handle = mhdf_openDenseTagData( file, "GLOBAL_ID", mhdf_node_type_handle( ), &numtag, sptr );CHK_ERR( sptr );
00187             assert( numtag == numnode );
00188             mhdf_readDenseTag( handle, 0, numtag, H5T_NATIVE_UINT, nodeids, sptr );CHK_ERR( sptr );
00189             mhdf_closeData( file, handle, sptr );CHK_ERR( sptr );
00190             have_nodeids = 1;
00191         }
00192         /* Check for and read dense-format tag data for hexes */
00193         havedense = mhdf_haveDenseTag( file, "GLOBAL_ID", hexgroup, sptr );CHK_ERR( sptr );
00194         if( havedense )
00195         {
00196             handle = mhdf_openDenseTagData( file, "GLOBAL_ID", hexgroup, &numtag, sptr );CHK_ERR( sptr );
00197             assert( numtag == numhex );
00198             mhdf_readDenseTag( handle, 0, numtag, H5T_NATIVE_UINT, hexids, sptr );CHK_ERR( sptr );
00199             mhdf_closeData( file, handle, sptr );CHK_ERR( sptr );
00200             have_hexids = 1;
00201         }
00202         /* Check for and read sparse-format tag data */
00203         if( havesparse )
00204         {
00205             mhdf_openSparseTagData( file, "GLOBAL_ID", &numtag, &junk, sparse_handle, sptr );CHK_ERR( sptr );
00206             sparse_entities = (unsigned*)malloc( numtag * sizeof( unsigned ) );
00207             mhdf_readSparseTagEntities( sparse_handle[ 0 ], 0, numtag, H5T_NATIVE_UINT, sparse_entities, sptr );CHK_ERR( sptr );
00208             sparse_ids = (unsigned*)malloc( numtag * sizeof( unsigned ) );
00209             mhdf_readSparseTagValues( sparse_handle[ 1 ], 0, numtag, H5T_NATIVE_UINT, sparse_ids, sptr );CHK_ERR( sptr );
00210             mhdf_closeData( file, sparse_handle[ 0 ], sptr );CHK_ERR( sptr );
00211             mhdf_closeData( file, sparse_handle[ 1 ], sptr );CHK_ERR( sptr );
00212 
00213             /* Set hex and node ids from sparse tag data */
00214             for( i = 0; i < numtag; ++i )
00215             {
00216                 fileid = sparse_entities[ i ];
00217                 globalid = sparse_ids[ i ];
00218                 if( fileid >= nodestart && fileid - nodestart < numnode )
00219                 {
00220                     nodeids[ fileid - nodestart ] = globalid;
00221                     ++ncount;
00222                 }
00223                 else if( fileid >= hexstart && fileid - hexstart < numhex )
00224                 {
00225                     hexids[ fileid - hexstart ] = globalid;
00226                     ++hcount;
00227                 }
00228             }
00229             free( sparse_ids );
00230             free( sparse_entities );
00231 
00232             /* make sure there was an ID for each node and each hex */
00233             if( ncount == numnode ) have_nodeids = 1;
00234             if( hcount == numhex ) have_hexids = 1;
00235 
00236         } /* end have sparse tag for GLOBAL_ID */
00237     } /* end have GLOBAL_ID tag */
00238 
00239     /* done with input file */
00240     free( hexgroup );
00241     mhdf_closeFile( file, sptr );CHK_ERR( sptr );
00242 
00243     /* if no GLOBAL_ID, just use incrementing values */
00244     if( !have_nodeids )
00245         for( i = 0; i < numnode; ++i )
00246             nodeids[ i ] = i + 1;
00247     if( !have_hexids )
00248         for( i = 0; i < numhex; ++i )
00249             hexids[ i ] = i + 1;
00250 
00251     /* write out as gmesh file version 1.0 */
00252 
00253     /* get gmsh type for hexahedrons */
00254     if( nodes_per_hex == 8 )
00255         gmsh_type = 5;
00256     else if( nodes_per_hex == 27 )
00257         gmsh_type = 12;
00258     else
00259     {
00260         fprintf( stderr, "Cannot store %d node hex in gmsh file.\n", nodes_per_hex );
00261         exit( 4 );
00262     }
00263 
00264     /* open file */
00265     gmsh = fopen( gmsh_filename, "w" );
00266 
00267     /* Write node data.  If dimension is less than 3,
00268        write zero for other coordinate values.  In the
00269        (highly unlikely) case that dimension is greater
00270        than three, disregard higher-dimension coordinate
00271        values. */
00272     fprintf( gmsh, "$NOD\n" );
00273     fprintf( gmsh, "%lu\n", numnode );
00274     for( i = 0; i < numnode; ++i )
00275     {
00276         x = nodecoords[ dimension * i ];
00277         y = z = 0.0;
00278         if( dimension > 1 )
00279         {
00280             y = nodecoords[ dimension * i + 1 ];
00281             if( dimension > 2 ) { z = nodecoords[ dimension * i + 2 ]; }
00282         }
00283         fprintf( gmsh, "%u %f %f %f\n", nodeids[ i ], x, y, z );
00284     }
00285 
00286     /* Write element connectivity data */
00287     fprintf( gmsh, "$ENDNOD\n$ELM\n" );
00288     fprintf( gmsh, "%lu\n", numhex );
00289     for( i = 0; i < numhex; ++i )
00290     {
00291         fprintf( gmsh, "%u %u 1 1 %d", hexids[ i ], gmsh_type, nodes_per_hex );
00292         /* connectivity list for this hex */
00293         connectivity = hexconnectivity + i * nodes_per_hex;
00294         for( j = 0; j < nodes_per_hex; ++j )
00295         {
00296             /* get offset in node list from file id */
00297             node_offset = connectivity[ j ] - nodestart;
00298             /* get node id from ID list */
00299             node_id = nodeids[ node_offset ];
00300             fprintf( gmsh, " %u", node_id );
00301         }
00302         fprintf( gmsh, "\n" );
00303     }
00304     fprintf( gmsh, "$ENDELM\n" );
00305     fclose( gmsh );
00306     return 0;
00307 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines