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