Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
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