Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
Mesh I/O Operations

Functions for reading and writing mesh files. More...

+ Collaboration diagram for Mesh I/O Operations:

Functions

ErrCode iMOAB_ReadHeaderInfo (const iMOAB_String filename, int *num_global_vertices, int *num_global_elements, int *num_dimension, int *num_parts)
 Read mesh file header information without loading full mesh. More...
 
ErrCode iMOAB_LoadMesh (iMOAB_AppID pid, const iMOAB_String filename, const iMOAB_String read_options, int *num_ghost_layers)
 Load mesh file into application's mesh set. More...
 
ErrCode iMOAB_WriteMesh (iMOAB_AppID pid, const iMOAB_String filename, const iMOAB_String write_options)
 Write application's mesh to file. More...
 
ErrCode iMOAB_WriteLocalMesh (iMOAB_AppID pid, iMOAB_String prefix)
 Write each process's local mesh to separate file for debugging. More...
 

Detailed Description

Functions for reading and writing mesh files.

Function Documentation

◆ iMOAB_LoadMesh()

ErrCode iMOAB_LoadMesh ( iMOAB_AppID  pid,
const iMOAB_String  filename,
const iMOAB_String  read_options,
int *  num_ghost_layers 
)

Load mesh file into application's mesh set.

Load a MOAB mesh file in parallel and exchange ghost layers as requested.

Loads mesh from file (HDF5, Exodus, VTK, etc.) into application's mesh set with optional ghost layer exchange for parallel simulations. Automatically configures parallel reading options.

Loading Process:
  1. Construct read options string from user options + automatic parallel settings
  2. Add PARALLEL_COMM option for parallel HDF5/NetCDF files
  3. Add ghost layer options (PARALLEL_GHOSTS, PARTITION_DISTRIBUTE) if requested
  4. Load mesh into application's file set using MOAB::load_file()
  5. Update mesh information (vertex/element counts, ranges, etc.)
  6. Exchange ghost layers if num_ghost_layers > 0
Parameters
[in]pidApplication ID
[in]filenamePath to mesh file to load
[in]read_optionsOptional reader options (semicolon-separated, can be NULL)
[in]num_ghost_layersNumber of ghost element layers to exchange (0 for none)
Precondition
Application must be registered via iMOAB_RegisterApplication
File must exist and be readable
For parallel: MPI must be initialized
Postcondition
Mesh loaded into application's file set
Mesh info updated (vertices, elements, ranges)
Ghost layers exchanged if requested
Note
Supported formats: HDF5 (.h5m), Exodus (.exo), VTK (.vtk), NetCDF (.nc), etc.
PARALLEL_COMM option automatically added for parallel HDF5/NetCDF
Ghost exchange requires PARALLEL_GHOSTS and PARTITION_DISTRIBUTE options
Warning
Do not manually specify PARALLEL_COMM in read_options (will cause error)
Returns
moab::MB_SUCCESS on success, error code otherwise
See also
iMOAB_WriteMesh(), iMOAB_UpdateMeshInfo()

Definition at line 895 of file iMOAB.cpp.

899 {
900  IMOAB_CHECKPOINTER( filename, 2 );
901  IMOAB_ASSERT( strlen( filename ), "Invalid filename length." );
902  IMOAB_CHECKPOINTER( num_ghost_layers, 4 );
903 
904  // make sure we use the file set and pcomm associated with the *pid
905  std::ostringstream newopts;
906  if( read_options ) newopts << read_options;
907 
908 #ifdef MOAB_HAVE_MPI
909 
911  {
912  if( context.worldprocs > 1 )
913  {
914  std::string opts( ( read_options ? read_options : "" ) );
915  std::string pcid( "PARALLEL_COMM=" );
916  std::size_t found = opts.find( pcid );
917 
918  if( found != std::string::npos )
919  {
920  std::cerr << " cannot specify PARALLEL_COMM option, it is implicit \n";
921  return moab::MB_FAILURE;
922  }
923 
924  // in serial, apply PARALLEL_COMM option only for h5m files; it does not work for .g
925  // files (used in test_remapping)
926  std::string filen( filename );
927  std::string::size_type idx = filen.rfind( '.' );
928 
929  if( idx != std::string::npos )
930  {
931  ParallelComm* pco = context.appDatas[*pid].pcomm;
932  std::string extension = filen.substr( idx + 1 );
933  if( ( extension == std::string( "h5m" ) ) || ( extension == std::string( "nc" ) ) )
934  newopts << ";;PARALLEL_COMM=" << pco->get_id();
935  }
936 
937  if( *num_ghost_layers >= 1 )
938  {
939  // if we want ghosts, we will want additional entities, the last .1
940  // because the addl ents can be edges, faces that are part of the neumann sets
941  std::string pcid2( "PARALLEL_GHOSTS=" );
942  std::size_t found2 = opts.find( pcid2 );
943 
944  if( found2 != std::string::npos )
945  {
946  std::cout << " PARALLEL_GHOSTS option is already specified, ignore passed "
947  "number of layers \n";
948  }
949  else
950  {
951  // dimension of primary entities is 3 here, but it could be 2 for climate
952  // meshes; we would need to pass PARALLEL_GHOSTS explicitly for 2d meshes, for
953  // example: ";PARALLEL_GHOSTS=2.0.1"
954  newopts << ";PARALLEL_GHOSTS=3.0." << *num_ghost_layers << ".3";
955  }
956  }
957  }
958  }
959 #else
960  IMOAB_ASSERT( *num_ghost_layers == 0, "Cannot provide ghost layers in serial." );
961 #endif
962 
963  // Now let us actually load the MOAB file with the appropriate read options
964  MB_CHK_SET_ERR( context.MBI->load_file( filename, &context.appDatas[*pid].file_set, newopts.str().c_str() ),
965  "can't load file" );
966 
967 #ifdef VERBOSE
968  // some debugging stuff
969  std::ostringstream outfile;
970 #ifdef MOAB_HAVE_MPI
971  ParallelComm* pco = context.appDatas[*pid].pcomm;
972  int rank = pco->rank();
973  int nprocs = pco->size();
974  outfile << "TaskMesh_n" << nprocs << "." << rank << ".h5m";
975 #else
976  outfile << "TaskMesh_n1.0.h5m";
977 #endif
978  // the mesh contains ghosts too, but they are not part of mat/neumann set
979  // write in serial the file, to see what tags are missing
980  MB_CHK_SET_ERR( context.MBI->write_file( outfile.str().c_str() ),
981  "can't write file" ); // everything on current task, written in serial
982 #endif
983 
984  // Update ghost layer information
985  context.appDatas[*pid].num_ghost_layers = *num_ghost_layers;
986 
987  // Update mesh information
988  return iMOAB_UpdateMeshInfo( pid );
989 }

References GlobalContext::appDatas, context, moab::ParallelComm::get_id(), IMOAB_ASSERT, IMOAB_CHECKPOINTER, iMOAB_UpdateMeshInfo(), moab::Interface::load_file(), MB_CHK_SET_ERR, GlobalContext::MBI, GlobalContext::MPI_initialized, moab::ParallelComm::rank(), moab::ParallelComm::size(), GlobalContext::worldprocs, and moab::Interface::write_file().

◆ iMOAB_ReadHeaderInfo()

ErrCode iMOAB_ReadHeaderInfo ( const iMOAB_String  filename,
int *  num_global_vertices,
int *  num_global_elements,
int *  num_dimension,
int *  num_parts 
)

Read mesh file header information without loading full mesh.

It should be called on master task only, and information obtained could be broadcasted by the user. It is a fast lookup in the header of the file.

Quickly extracts metadata from HDF5 mesh file including vertex count, element count, spatial dimension, and partition count. Useful for memory planning before full load.

Implementation:
  • Opens HDF5 file in read-only mode using mhdf library
  • Reads file summary without loading actual mesh data
  • Counts elements by type (edges, faces, regions)
  • Extracts partition information from parallel decomposition tags
Parameters
[in]filenamePath to HDF5 mesh file
[out]num_global_verticesTotal number of vertices in mesh
[out]num_global_elementsTotal number of elements in mesh (all types)
[out]num_dimensionSpatial dimension (2D or 3D)
[out]num_partsNumber of parallel partitions
Precondition
HDF5 support must be enabled (MOAB_HAVE_HDF5)
File must be valid HDF5 mesh file
Postcondition
Output parameters populated with file metadata
File remains closed (no mesh data loaded)
Note
Lightweight operation - does not load mesh into memory
All output parameters are optional (can be NULL)
Warning
Returns failure if HDF5 support not enabled
Returns
moab::MB_SUCCESS on success, moab::MB_FAILURE on error
See also
iMOAB_LoadMesh()

Definition at line 714 of file iMOAB.cpp.

719 {
720  IMOAB_CHECKPOINTER( filename, 1 );
721  IMOAB_ASSERT( strlen( filename ), "Invalid filename length." );
722 
723 #ifdef MOAB_HAVE_HDF5
724  std::string filen( filename );
725 
726  int edges = 0;
727  int faces = 0;
728  int regions = 0;
729  if( num_global_vertices ) *num_global_vertices = 0;
730  if( num_global_elements ) *num_global_elements = 0;
731  if( num_dimension ) *num_dimension = 0;
732  if( num_parts ) *num_parts = 0;
733 
734  mhdf_FileHandle file;
735  mhdf_Status status;
736  unsigned long max_id;
737  struct mhdf_FileDesc* data;
738 
739  file = mhdf_openFile( filen.c_str(), 0, &max_id, -1, &status );
740 
741  if( mhdf_isError( &status ) )
742  {
743  fprintf( stderr, "%s: %s\n", filename, mhdf_message( &status ) );
744  return moab::MB_FAILURE;
745  }
746 
747  data = mhdf_getFileSummary( file, H5T_NATIVE_ULONG, &status,
748  1 ); // will use extra set info; will get parallel partition tag info too!
749 
750  if( mhdf_isError( &status ) )
751  {
752  fprintf( stderr, "%s: %s\n", filename, mhdf_message( &status ) );
753  return moab::MB_FAILURE;
754  }
755 
756  if( num_dimension ) *num_dimension = data->nodes.vals_per_ent;
757  if( num_global_vertices ) *num_global_vertices = (int)data->nodes.count;
758 
759  for( int i = 0; i < data->num_elem_desc; i++ )
760  {
761  struct mhdf_ElemDesc* el_desc = &( data->elems[i] );
762  struct mhdf_EntDesc* ent_d = &( el_desc->desc );
763 
764  if( 0 == strcmp( el_desc->type, mhdf_EDGE_TYPE_NAME ) )
765  {
766  edges += ent_d->count;
767  }
768 
769  if( 0 == strcmp( el_desc->type, mhdf_TRI_TYPE_NAME ) )
770  {
771  faces += ent_d->count;
772  }
773 
774  if( 0 == strcmp( el_desc->type, mhdf_QUAD_TYPE_NAME ) )
775  {
776  faces += ent_d->count;
777  }
778 
779  if( 0 == strcmp( el_desc->type, mhdf_POLYGON_TYPE_NAME ) )
780  {
781  faces += ent_d->count;
782  }
783 
784  if( 0 == strcmp( el_desc->type, mhdf_TET_TYPE_NAME ) )
785  {
786  regions += ent_d->count;
787  }
788 
789  if( 0 == strcmp( el_desc->type, mhdf_PYRAMID_TYPE_NAME ) )
790  {
791  regions += ent_d->count;
792  }
793 
794  if( 0 == strcmp( el_desc->type, mhdf_PRISM_TYPE_NAME ) )
795  {
796  regions += ent_d->count;
797  }
798 
799  if( 0 == strcmp( el_desc->type, mdhf_KNIFE_TYPE_NAME ) )
800  {
801  regions += ent_d->count;
802  }
803 
804  if( 0 == strcmp( el_desc->type, mdhf_HEX_TYPE_NAME ) )
805  {
806  regions += ent_d->count;
807  }
808 
809  if( 0 == strcmp( el_desc->type, mhdf_POLYHEDRON_TYPE_NAME ) )
810  {
811  regions += ent_d->count;
812  }
813 
814  if( 0 == strcmp( el_desc->type, mhdf_SEPTAHEDRON_TYPE_NAME ) )
815  {
816  regions += ent_d->count;
817  }
818  }
819 
820  if( num_parts ) *num_parts = data->numEntSets[0];
821 
822  // is this required?
823  if( edges > 0 )
824  {
825  if( num_dimension ) *num_dimension = 1; // I don't think it will ever return 1
826  if( num_global_elements ) *num_global_elements = edges;
827  }
828 
829  if( faces > 0 )
830  {
831  if( num_dimension ) *num_dimension = 2;
832  if( num_global_elements ) *num_global_elements = faces;
833  }
834 
835  if( regions > 0 )
836  {
837  if( num_dimension ) *num_dimension = 3;
838  if( num_global_elements ) *num_global_elements = regions;
839  }
840 
841  mhdf_closeFile( file, &status );
842 
843  free( data );
844 
845 #else
846  std::cout << filename
847  << ": Please reconfigure with HDF5. Cannot retrieve header information for file "
848  "formats other than a h5m file.\n";
849  if( num_global_vertices ) *num_global_vertices = 0;
850  if( num_global_elements ) *num_global_elements = 0;
851  if( num_dimension ) *num_dimension = 0;
852  if( num_parts ) *num_parts = 0;
853 #endif
854 
855  return moab::MB_SUCCESS;
856 }

References mhdf_EntDesc::count, mhdf_ElemDesc::desc, mhdf_FileDesc::elems, IMOAB_ASSERT, IMOAB_CHECKPOINTER, MB_SUCCESS, mdhf_HEX_TYPE_NAME, mdhf_KNIFE_TYPE_NAME, mhdf_closeFile(), mhdf_EDGE_TYPE_NAME, mhdf_getFileSummary(), mhdf_isError(), mhdf_message(), mhdf_openFile(), mhdf_POLYGON_TYPE_NAME, mhdf_POLYHEDRON_TYPE_NAME, mhdf_PRISM_TYPE_NAME, mhdf_PYRAMID_TYPE_NAME, mhdf_QUAD_TYPE_NAME, mhdf_SEPTAHEDRON_TYPE_NAME, mhdf_TET_TYPE_NAME, mhdf_TRI_TYPE_NAME, mhdf_FileDesc::nodes, mhdf_FileDesc::num_elem_desc, mhdf_FileDesc::numEntSets, mhdf_ElemDesc::type, and mhdf_EntDesc::vals_per_ent.

◆ iMOAB_WriteLocalMesh()

ErrCode iMOAB_WriteLocalMesh ( iMOAB_AppID  pid,
iMOAB_String  prefix 
)

Write each process's local mesh to separate file for debugging.

Write a local MOAB mesh copy.

Creates per-process HDF5 file with naming convention: prefix_nprocs_rank.h5m. Useful for debugging parallel mesh distribution and ghost layer issues.

Parameters
[in]pidApplication ID
[in]prefixOutput file prefix (rank and process count appended automatically)
Precondition
Application must be registered and mesh loaded
Postcondition
Each process writes its local mesh to: prefix_<nprocs>_<rank>.h5m
Note
Output files show per-process mesh partition (useful for parallel debugging)
Files include both owned and ghost entities
Returns
moab::MB_SUCCESS on success, error code otherwise
See also
iMOAB_WriteMesh()

Definition at line 1131 of file iMOAB.cpp.

1132 {
1133  IMOAB_CHECKPOINTER( prefix, 2 );
1134  IMOAB_ASSERT( strlen( prefix ), "Invalid prefix string length." );
1135 
1136  // Construct filename with parallel decomposition info: prefix_nprocs_rank.h5m
1137  std::ostringstream file_name;
1138  int rank = 0, size = 1;
1139 #ifdef MOAB_HAVE_MPI
1140  ParallelComm* pcomm = context.appDatas[*pid].pcomm;
1141  rank = pcomm->rank();
1142  size = pcomm->size();
1143 #endif
1144  file_name << prefix << "_" << size << "_" << rank << ".h5m";
1145 
1146  // Write this process's local mesh partition to its own file
1147  MB_CHK_ERR( context.MBI->write_file( file_name.str().c_str(), 0, 0, &context.appDatas[*pid].file_set, 1 ) );
1148 
1149  return moab::MB_SUCCESS;
1150 }

References GlobalContext::appDatas, context, IMOAB_ASSERT, IMOAB_CHECKPOINTER, MB_CHK_ERR, MB_SUCCESS, GlobalContext::MBI, moab::ParallelComm::rank(), moab::ParallelComm::size(), and moab::Interface::write_file().

◆ iMOAB_WriteMesh()

ErrCode iMOAB_WriteMesh ( iMOAB_AppID  pid,
const iMOAB_String  filename,
const iMOAB_String  write_options 
)

Write application's mesh to file.

Write a MOAB mesh along with the solution tags to a file.

Writes mesh data from application's mesh set to file in various formats (HDF5, Exodus, VTK, etc.). Automatically includes GLOBAL_ID and PARALLEL_PARTITION tags for parallel simulations.

Writing Process:
  1. Construct write options from user options + automatic parallel settings
  2. Add PARALLEL=WRITE_PART for parallel HDF5 output if needed
  3. Append GLOBAL_ID tag if not already in tag list
  4. Append PARALLEL_PARTITION tag if available and not in tag list
  5. Write mesh using MOAB::write_file() with appropriate options
Parameters
[in]pidApplication ID
[in]filenameOutput file path
[in]write_optionsOptional writer options (semicolon-separated, can be NULL)
Precondition
Application must be registered and mesh loaded
For parallel: output directory must be writable by all processes
Postcondition
Mesh written to file with requested format
GLOBAL_ID and PARALLEL_PARTITION tags included if available
Note
Supported formats: HDF5 (.h5m), Exodus (.exo), VTK (.vtk), etc.
For parallel writes, use PARALLEL=WRITE_PART option
Tags in application's tagList are automatically written
Returns
moab::MB_SUCCESS on success, error code otherwise
See also
iMOAB_LoadMesh(), iMOAB_WriteLocalMesh()

Definition at line 1105 of file iMOAB.cpp.

1106 {
1107  return internal_WriteMesh( pid, filename, write_options );
1108 }

References internal_WriteMesh().