MOAB: Mesh Oriented datABase
(version 5.2.1)
|
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