Mesh Oriented datABase  (version 5.4.1)
Array-based unstructured mesh datastructure
ReadHDF5.hpp
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 2004 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 #ifndef READ_HDF5_HPP
00017 #define READ_HDF5_HPP
00018 
00019 #include <cstdlib>
00020 #include <list>
00021 #include "mhdf.h"
00022 #include "moab/Forward.hpp"
00023 #include "moab/ReadUtilIface.hpp"
00024 #include "moab/Range.hpp"
00025 #include "moab/ReaderIface.hpp"
00026 #include "moab/RangeMap.hpp"
00027 #include "DebugOutput.hpp"
00028 #include "HDF5Common.hpp"
00029 
00030 #ifdef MOAB_HAVE_MPI
00031 #include <moab_mpi.h>
00032 #endif
00033 
00034 namespace moab
00035 {
00036 
00037 class ParallelComm;
00038 class ReadHDF5Dataset;
00039 class CpuTimer;
00040 
00041 /**
00042  * \brief  Read mesh from MOAB HDF5 (.h5m) file.
00043  * \author Jason Kraftcheck
00044  * \date   18 April 2004
00045  */
00046 class ReadHDF5 : public ReaderIface
00047 {
00048   public:
00049 #ifdef MOAB_HAVE_MPI
00050     typedef MPI_Comm Comm;
00051 #else
00052     typedef int Comm;
00053 #endif
00054 
00055     static ReaderIface* factory( Interface* );
00056 
00057     ReadHDF5( Interface* iface );
00058 
00059     virtual ~ReadHDF5();
00060 
00061     /** Export specified meshsets to file
00062      * \param filename     The filename to export. Must end in <em>.mhdf</em>
00063      * \param export_sets  Array of handles to sets to export, or NULL to export all.
00064      * \param export_set_count Length of <code>export_sets</code> array.
00065      */
00066     ErrorCode load_file( const char* file_name,
00067                          const EntityHandle* file_set,
00068                          const FileOptions& opts,
00069                          const SubsetList* subset_list = 0,
00070                          const Tag* file_id_tag        = 0 );
00071 
00072     ErrorCode read_tag_values( const char* file_name,
00073                                const char* tag_name,
00074                                const FileOptions& opts,
00075                                std::vector< int >& tag_values_out,
00076                                const SubsetList* subset_list = 0 );
00077     Interface* moab() const
00078     {
00079         return iFace;
00080     }
00081 
00082     //! Store old HDF5 error handling function
00083     struct HDF5ErrorHandler
00084     {
00085         HDF5_Error_Func_Type func;
00086         void* data;
00087     };
00088 
00089   protected:
00090     ErrorCode load_file_impl( const FileOptions& opts );
00091 
00092     ErrorCode load_file_partial( const ReaderIface::IDTag* subset_list,
00093                                  int subset_list_length,
00094                                  int num_parts,
00095                                  int part_number,
00096                                  const FileOptions& opts );
00097 
00098     ErrorCode read_tag_values_all( int tag_index, std::vector< int >& results );
00099     ErrorCode read_tag_values_partial( int tag_index, const Range& file_ids, std::vector< int >& results );
00100 
00101     enum ReadTimingValues
00102     {
00103         TOTAL_TIME = 0,
00104         SET_META_TIME,
00105         SUBSET_IDS_TIME,
00106         GET_PARTITION_TIME,
00107         GET_SET_IDS_TIME,
00108         GET_SET_CONTENTS_TIME,
00109         GET_POLYHEDRA_TIME,
00110         GET_ELEMENTS_TIME,
00111         GET_NODES_TIME,
00112         GET_NODEADJ_TIME,
00113         GET_SIDEELEM_TIME,
00114         UPDATECONN_TIME,
00115         ADJACENCY_TIME,
00116         DELETE_NON_SIDEELEM_TIME,
00117         READ_SET_IDS_RECURS_TIME,
00118         FIND_SETS_CONTAINING_TIME,
00119         READ_SETS_TIME,
00120         READ_TAGS_TIME,
00121         STORE_FILE_IDS_TIME,
00122         READ_QA_TIME,
00123         NUM_TIMES
00124     };
00125 
00126     void print_times();
00127 
00128   private:
00129     ErrorCode init();
00130 
00131     inline int is_error( mhdf_Status& status )
00132     {
00133         int i;
00134         if( ( i = mhdf_isError( &status ) ) ) MB_SET_ERR_CONT( mhdf_message( &status ) );
00135         return i;
00136     }
00137 
00138     //! The size of the data buffer (<code>dataBuffer</code>).
00139     int bufferSize;
00140     //! A memory buffer to use for all I/O operations.
00141     char* dataBuffer;
00142 
00143     //! Interface pointer passed to constructor
00144     Interface* iFace;
00145 
00146     //! The file handle from the mhdf library
00147     mhdf_FileHandle filePtr;
00148 
00149     //! File summary
00150     mhdf_FileDesc* fileInfo;
00151 
00152     //! Map from File ID to MOAB handle
00153     typedef RangeMap< long, EntityHandle > IDMap;
00154     IDMap idMap;
00155 
00156     //! Cache pointer to read util
00157     ReadUtilIface* readUtil;
00158 
00159     //! The type of an EntityHandle
00160     hid_t handleType;
00161 
00162     //! List of connectivity arrays for which conversion from file ID
00163     //! to handle was deferred until later.
00164     struct IDConnectivity
00165     {
00166         EntityHandle handle;  // Start_handle
00167         size_t count;         // Num entities
00168         int nodes_per_elem;   // Per-element connectivity length
00169         EntityHandle* array;  // Connectivity array
00170     };
00171     //! List of connectivity arrays for which conversion from file ID
00172     //! to handle was deferred until later.
00173     std::vector< IDConnectivity > idConnectivityList;
00174 
00175     //! Read/write property handle
00176     //! indepIO -> independent IO during true parallel read
00177     //! collIO  -> collective IO during true parallel read
00178     //! Both are H5P_DEFAULT for serial IO and collective
00179     //! when reading the entire file on all processors.
00180     hid_t indepIO, collIO;
00181 
00182     ParallelComm* myPcomm;
00183 
00184     //! Use IODebugTrack instances to verify reads.
00185     //! Enable with the DEBUG_OVERLAPS option.
00186     bool debugTrack;
00187     //! Debug output. Verbosity controlled with DEBUG_FORMAT option.
00188     DebugOutput dbgOut;
00189     //! Doing true parallel read (PARALLEL=READ_PART)
00190     bool nativeParallel;
00191     //! MPI_Comm value (unused if \c !nativeParallel)
00192     Comm* mpiComm;
00193 
00194     //! Flags for some behavior that can be changed through
00195     //! reader options
00196     bool blockedCoordinateIO;
00197     bool bcastSummary;
00198     bool bcastDuplicateReads;
00199 
00200     //! Store old HDF5 error handling function
00201     HDF5ErrorHandler errorHandler;
00202 
00203     long ( *setMeta )[4];
00204 
00205     double _times[NUM_TIMES];
00206     CpuTimer* timer;
00207     bool cputime;
00208     ErrorCode read_all_set_meta();
00209 
00210     ErrorCode set_up_read( const char* file_name, const FileOptions& opts );
00211     ErrorCode clean_up_read( const FileOptions& opts );
00212 
00213     //! Given a list of tags and values, get the file ids for the
00214     //! corresponding entities in the file.
00215     ErrorCode get_subset_ids( const ReaderIface::IDTag* subset_list, int subset_list_length, Range& file_ids_out );
00216 
00217     /**\brief Remove all but the specified fraction of sets from the passed range
00218      *
00219      * Select a subset of the gathered set of file ids to read in based on
00220      * communicator size and rank.
00221      *\param tmp_file_ids As input: sets to be read on all procs.
00222      *                    As output: sets to read on this proc.
00223      *\param num_parts    communicator size
00224      *\param part_number  communicator rank
00225      */
00226     ErrorCode get_partition( Range& tmp_file_ids, int num_parts, int part_number );
00227 
00228     ErrorCode read_nodes( const Range& node_file_ids );
00229 
00230     // Read elements in fileInfo->elems[index]
00231     ErrorCode read_elems( int index );
00232 
00233     // Read subset of elements in fileInfo->elems[index]
00234     ErrorCode read_elems( int index, const Range& file_ids, Range* node_ids = 0 );
00235 
00236     //! Read element connectivity.
00237     //!
00238     //!\param node_ids  If this is non-null, the union of the connectivity list
00239     //!                 for all elements is passed back as FILE IDS in this
00240     //!                 range AND the connectivity list is left in the form
00241     //!                 of file IDs (NOT NODE HANDLES).
00242     ErrorCode read_elems( const mhdf_ElemDesc& elems, const Range& file_ids, Range* node_ids = 0 );
00243 
00244     //! Update connectivity data for all element groups for which read_elems
00245     //! was called with a non-null \c node_ids argument.
00246     ErrorCode update_connectivity();
00247 
00248     // Read connectivity data for a list of element file ids.
00249     // passing back the file IDs for the element connectivity
00250     // w/out actually creating any elements in MOAB.
00251     ErrorCode read_elems( int index, const Range& element_file_ids, Range& node_file_ids );
00252 
00253     // Scan all elements in group. For each element for which all vertices
00254     // are contained in idMap (class member), read the element. All new
00255     // elements are added to idMap.
00256     //
00257     // NOTE: Collective IO calls in parallel.
00258     ErrorCode read_node_adj_elems( const mhdf_ElemDesc& group, Range* read_entities = 0 );
00259 
00260     // Scan all elements in specified file table. For each element for
00261     // which all vertices are contained in idMap (class member), read the
00262     // element. All new elements are added to idMap.
00263     //
00264     // NOTE: Collective IO calls in parallel.
00265     ErrorCode read_node_adj_elems( const mhdf_ElemDesc& group, hid_t connectivity_handle, Range* read_entities = 0 );
00266 
00267     //! Read poly(gons|hedra)
00268     ErrorCode read_poly( const mhdf_ElemDesc& elems, const Range& file_ids );
00269 
00270     //! Clean up elements that were a) read because we had read all of the
00271     //! nodes and b) weren't actually sides of the top-dimension elements
00272     //! we were trying to read.
00273     ErrorCode delete_non_side_elements( const Range& side_ents );
00274 
00275     //! Read sets
00276     ErrorCode read_sets( const Range& set_file_ids );
00277 
00278     ErrorCode read_adjacencies( hid_t adjacency_table, long table_length );
00279 
00280     //! Create tag and read all data.
00281     ErrorCode read_tag( int index );
00282 
00283     //! Create new tag or verify type matches existing tag
00284     ErrorCode create_tag( const mhdf_TagDesc& info, Tag& handle, hid_t& type );
00285 
00286     //! Read dense tag for all entities
00287     ErrorCode read_dense_tag( Tag tag_handle,
00288                               const char* ent_name,
00289                               hid_t hdf_read_type,
00290                               hid_t data_table,
00291                               long start_id,
00292                               long count );
00293 
00294     //! Read sparse tag for all entities.
00295     ErrorCode read_sparse_tag( Tag tag_handle,
00296                                hid_t hdf_read_type,
00297                                hid_t ent_table,
00298                                hid_t val_table,
00299                                long num_entities );
00300 
00301     //! Read variable-length tag for all entities.
00302     ErrorCode read_var_len_tag( Tag tag_handle,
00303                                 hid_t hdf_read_type,
00304                                 hid_t ent_table,
00305                                 hid_t val_table,
00306                                 hid_t off_table,
00307                                 long num_entities,
00308                                 long num_values );
00309 
00310     /**\brief Read index table for sparse tag.
00311      *
00312      * Read ID table for a sparse or variable-length tag, returning
00313      * the handles and offsets within the table for each file ID
00314      * that corresponds to an entity we've read from the file (an
00315      * entity that is in \c idMap).
00316      *
00317      * \param id_table     The MOAB handle for the tag
00318      * \param start_offset Some non-zero value because ranges (in this case
00319      *                     the offset_range) cannot contain zeros.
00320      * \param offset_range Output: The offsets in the id table for which IDs
00321      *                     that occur in \c idMap were found. All values
00322      *                     are increased by \c start_offset to avoid
00323      *                     putting zeros in the range.
00324      * \param handle_range Output: For each valid ID read from the table,
00325      *                     the corresponding entity handle. Note: if
00326      *                     the IDs did not occur in handle order, then
00327      *                     this will be empty. Use \c handle_vect instead.
00328      * \param handle_vect  Output: For each valid ID read from the table,
00329      *                     the corresponding entity handle. Note: if
00330      *                     the IDs occurred in handle order, then
00331      *                     this will be empty. Use \c handle_range instead.
00332      */
00333     ErrorCode read_sparse_tag_indices( const char* name,
00334                                        hid_t id_table,
00335                                        EntityHandle start_offset,
00336                                        Range& offset_range,
00337                                        Range& handle_range,
00338                                        std::vector< EntityHandle >& handle_vect );
00339 
00340     ErrorCode read_qa( EntityHandle file_set );
00341 
00342   public:
00343     ErrorCode convert_id_to_handle( EntityHandle* in_out_array, size_t array_length );
00344 
00345     void convert_id_to_handle( EntityHandle* in_out_array, size_t array_length, size_t& array_length_out ) const
00346     {
00347         return convert_id_to_handle( in_out_array, array_length, array_length_out, idMap );
00348     }
00349 
00350     ErrorCode convert_range_to_handle( const EntityHandle* ranges, size_t num_ranges, Range& merge );
00351 
00352     static void convert_id_to_handle( EntityHandle* in_out_array,
00353                                       size_t array_length,
00354                                       const RangeMap< long, EntityHandle >& id_map );
00355 
00356     static void convert_id_to_handle( EntityHandle* in_out_array,
00357                                       size_t array_length,
00358                                       size_t& array_length_out,
00359                                       const RangeMap< long, EntityHandle >& id_map );
00360 
00361     static void convert_range_to_handle( const EntityHandle* ranges,
00362                                          size_t num_ranges,
00363                                          const RangeMap< long, EntityHandle >& id_map,
00364                                          Range& merge );
00365 
00366     ErrorCode insert_in_id_map( const Range& file_ids, EntityHandle start_id );
00367 
00368     ErrorCode insert_in_id_map( long file_id, EntityHandle handle );
00369 
00370   private:
00371     /**\brief Search for entities with specified tag values
00372      *
00373      *\NOTE For parallel reads, this function does collective IO.
00374      *
00375      *\param tag_index  Index into info->tags specifying which tag to search.
00376      *\param sorted_values  List of tag values to check for, in ascending sorted
00377      *                  order.
00378      *\param file_ids_out  File IDs for entities with specified tag values.
00379      */
00380     ErrorCode search_tag_values( int tag_index,
00381                                  const std::vector< int >& sorted_values,
00382                                  Range& file_ids_out,
00383                                  bool sets_only = false );
00384 
00385     /**\brief Search for entities with specified tag
00386      *
00387      *\NOTE For parallel reads, this function does collective IO.
00388      *
00389      *\param tag_index  Index into info->tags specifying which tag to search.
00390      *\param file_ids_out  File IDs for entities with specified tag values.
00391      */
00392     ErrorCode get_tagged_entities( int tag_index, Range& file_ids_out );
00393 
00394     /**\brief Search a table of tag data for a specified set of values.
00395      *
00396      * Search a table of tag values, returning the indices into the table
00397      * at which matches were found.
00398      *\NOTE For parallel reads, this function does collective IO.
00399      *
00400      *\param info       Summary of data contained in file.
00401      *\param tag_table     HDF5/mhdf handle for tag values
00402      *\param table_size    Number of values in table
00403      *\param sorted_values Sorted list of values to search for.
00404      *\param value_indices Output: Offsets into the table of data at which
00405      *                       matching values were found.
00406      */
00407     ErrorCode search_tag_values( hid_t tag_table,
00408                                  unsigned long table_size,
00409                                  const std::vector< int >& sorted_values,
00410                                  std::vector< EntityHandle >& value_indices );
00411 
00412     /**\brief Get the file IDs for nodes and elements contained in sets.
00413      *
00414      * Read the contents for the specified sets and return the file IDs
00415      * of all nodes and elements contained within those sets.
00416      *\param sets       Container of file IDs designating entity sets.
00417      *\param file_ids   Output: File IDs of entities contained in sets.
00418      */
00419     ErrorCode get_set_contents( const Range& sets, Range& file_ids );
00420 
00421     /** Given a list of file IDs for entity sets, find all contained
00422      *  or child sets (at any depth) and append them to the Range
00423      *  of file IDs.
00424      */
00425     ErrorCode read_set_ids_recursive( Range& sets_in_out, bool containted_sets, bool child_sets );
00426 
00427     /** Find all sets containing one or more entities read from the file
00428      *  and added to idMap
00429      */
00430     ErrorCode find_sets_containing( Range& sets_out, bool read_set_containing_parents );
00431 
00432     /**\brief Read sets from file into MOAB for partial read of file.
00433      *
00434      * Given the file IDs for entity sets (sets_in) and elements and
00435      * nodes (id_map), read in all sets containing any of the elements
00436      * or nodes and all sets that are (recursively) children of any
00437      * other set to be read (those in sets_in or those containing any
00438      * already-read element or node.)
00439      *\param sets_in    File IDs for sets to read (unconditionally)
00440      */
00441     ErrorCode read_sets_partial( const Range& sets_in );
00442 
00443     /** Find file IDs of sets containing any entities in the passed id_map */
00444     ErrorCode find_sets_containing( hid_t content_handle,
00445                                     hid_t content_type,
00446                                     long content_len,
00447                                     bool read_set_containing_parents,
00448                                     Range& file_ids );
00449 
00450   public:
00451     enum SetMode
00452     {
00453         CONTENT = 0,
00454         CHILD   = 1,
00455         PARENT  = 2
00456     };
00457 
00458   private:
00459     // Read the set data specified by by which_data.
00460     // Update set data in MOAB according to which_data,
00461     // unless file_ids_out is non-null. If file_ids_out is
00462     // non-null, then return the file IDs in the passed
00463     // range and do not make any changes to MOAB data
00464     // structures. If file_ids_out is NULL, then set_start_handle
00465     // is ignored.
00466     ErrorCode read_set_data( const Range& set_file_ids,
00467                              EntityHandle set_start_handle,
00468                              ReadHDF5Dataset& set_data_set,
00469                              SetMode which_data,
00470                              Range* file_ids_out = 0 );
00471 
00472     /**\brief Store file IDS in tag values
00473      *
00474      * Copy file ID from IDMap for each entity read from file
00475      * into a tag value on the entity.
00476      */
00477     ErrorCode store_file_ids( Tag tag );
00478 
00479     /**\brief Store sets file IDS in a custom tag
00480      *
00481      * Copy sets file ID from IDMap for each set read from file
00482      *  into a custom tag on the sets
00483      *  needed now for the VisIt plugin, to identify sets read
00484      */
00485     ErrorCode store_sets_file_ids();
00486 
00487     /**\brief Find index in mhdf_FileDesc* fileInfo for specified tag name
00488      *
00489      * Given a tag name, find its index in fileInfo and verify that
00490      * each tag value is a single integer.
00491      */
00492     ErrorCode find_int_tag( const char* name, int& index_out );
00493 
00494     void debug_barrier_line( int lineno );
00495 };
00496 
00497 }  // namespace moab
00498 
00499 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines