Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
ReadHDF5.hpp
Go to the documentation of this file.
1 /**
2  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3  * storing and accessing finite element mesh data.
4  *
5  * Copyright 2004 Sandia Corporation. Under the terms of Contract
6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7  * retains certain rights in this software.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  */
15 
16 #ifndef READ_HDF5_HPP
17 #define READ_HDF5_HPP
18 
19 #include <cstdlib>
20 #include <list>
21 #include "mhdf.h"
22 #include "moab/Forward.hpp"
23 #include "moab/ReadUtilIface.hpp"
24 #include "moab/Range.hpp"
25 #include "moab/ReaderIface.hpp"
26 #include "moab/RangeMap.hpp"
27 #include "DebugOutput.hpp"
28 #include "HDF5Common.hpp"
29 
30 #ifdef MOAB_HAVE_MPI
31 #include <moab_mpi.h>
32 #endif
33 
34 namespace moab
35 {
36 
37 class ParallelComm;
38 class ReadHDF5Dataset;
39 class CpuTimer;
40 
41 /**
42  * \brief Read mesh from MOAB HDF5 (.h5m) file.
43  * \author Jason Kraftcheck
44  * \date 18 April 2004
45  */
46 class ReadHDF5 : public ReaderIface
47 {
48  public:
49 #ifdef MOAB_HAVE_MPI
50  typedef MPI_Comm Comm;
51 #else
52  typedef int Comm;
53 #endif
54 
55  static ReaderIface* factory( Interface* );
56 
58 
59  virtual ~ReadHDF5();
60 
61  /** Export specified meshsets to file
62  * \param filename The filename to export. Must end in <em>.mhdf</em>
63  * \param export_sets Array of handles to sets to export, or NULL to export all.
64  * \param export_set_count Length of <code>export_sets</code> array.
65  */
66  ErrorCode load_file( const char* file_name,
67  const EntityHandle* file_set,
68  const FileOptions& opts,
69  const SubsetList* subset_list = 0,
70  const Tag* file_id_tag = 0 );
71 
72  ErrorCode read_tag_values( const char* file_name,
73  const char* tag_name,
74  const FileOptions& opts,
75  std::vector< int >& tag_values_out,
76  const SubsetList* subset_list = 0 );
77  Interface* moab() const
78  {
79  return iFace;
80  }
81 
82  //! Store old HDF5 error handling function
84  {
86  void* data;
87  };
88 
89  protected:
90  ErrorCode load_file_impl( const FileOptions& opts );
91 
93  int subset_list_length,
94  int num_parts,
95  int part_number,
96  const FileOptions& opts );
97 
98  ErrorCode read_tag_values_all( int tag_index, std::vector< int >& results );
99  ErrorCode read_tag_values_partial( int tag_index, const Range& file_ids, std::vector< int >& results );
100 
102  {
123  NUM_TIMES
124  };
125 
126  void print_times();
127 
128  private:
129  ErrorCode init();
130 
131  inline int is_error( mhdf_Status& status )
132  {
133  int i;
134  if( ( i = mhdf_isError( &status ) ) ) MB_SET_ERR_CONT( mhdf_message( &status ) );
135  return i;
136  }
137 
138  //! The size of the data buffer (<code>dataBuffer</code>).
140  //! A memory buffer to use for all I/O operations.
141  char* dataBuffer;
142 
143  //! Interface pointer passed to constructor
145 
146  //! The file handle from the mhdf library
148 
149  //! File summary
151 
152  //! Map from File ID to MOAB handle
155 
156  //! Cache pointer to read util
158 
159  //! The type of an EntityHandle
160  hid_t handleType;
161 
162  //! List of connectivity arrays for which conversion from file ID
163  //! to handle was deferred until later.
165  {
166  EntityHandle handle; // Start_handle
167  size_t count; // Num entities
168  int nodes_per_elem; // Per-element connectivity length
169  EntityHandle* array; // Connectivity array
170  };
171  //! List of connectivity arrays for which conversion from file ID
172  //! to handle was deferred until later.
173  std::vector< IDConnectivity > idConnectivityList;
174 
175  //! Read/write property handle
176  //! indepIO -> independent IO during true parallel read
177  //! collIO -> collective IO during true parallel read
178  //! Both are H5P_DEFAULT for serial IO and collective
179  //! when reading the entire file on all processors.
180  hid_t indepIO, collIO;
181 
183 
184  //! Use IODebugTrack instances to verify reads.
185  //! Enable with the DEBUG_OVERLAPS option.
187  //! Debug output. Verbosity controlled with DEBUG_FORMAT option.
189  //! Doing true parallel read (PARALLEL=READ_PART)
191  //! MPI_Comm value (unused if \c !nativeParallel)
193 
194  //! Flags for some behavior that can be changed through
195  //! reader options
199 
200  //! Store old HDF5 error handling function
202 
203  long ( *setMeta )[4];
204 
205  double _times[NUM_TIMES];
207  bool cputime;
209 
210  ErrorCode set_up_read( const char* file_name, const FileOptions& opts );
211  ErrorCode clean_up_read( const FileOptions& opts );
212 
213  //! Given a list of tags and values, get the file ids for the
214  //! corresponding entities in the file.
215  ErrorCode get_subset_ids( const ReaderIface::IDTag* subset_list, int subset_list_length, Range& file_ids_out );
216 
217  /**\brief Remove all but the specified fraction of sets from the passed range
218  *
219  * Select a subset of the gathered set of file ids to read in based on
220  * communicator size and rank.
221  *\param tmp_file_ids As input: sets to be read on all procs.
222  * As output: sets to read on this proc.
223  *\param num_parts communicator size
224  *\param part_number communicator rank
225  */
226  ErrorCode get_partition( Range& tmp_file_ids, int num_parts, int part_number );
227 
228  ErrorCode read_nodes( const Range& node_file_ids );
229 
230  // Read elements in fileInfo->elems[index]
231  ErrorCode read_elems( int index );
232 
233  // Read subset of elements in fileInfo->elems[index]
234  ErrorCode read_elems( int index, const Range& file_ids, Range* node_ids = 0 );
235 
236  //! Read element connectivity.
237  //!
238  //!\param node_ids If this is non-null, the union of the connectivity list
239  //! for all elements is passed back as FILE IDS in this
240  //! range AND the connectivity list is left in the form
241  //! of file IDs (NOT NODE HANDLES).
242  ErrorCode read_elems( const mhdf_ElemDesc& elems, const Range& file_ids, Range* node_ids = 0 );
243 
244  //! Update connectivity data for all element groups for which read_elems
245  //! was called with a non-null \c node_ids argument.
247 
248  // Read connectivity data for a list of element file ids.
249  // passing back the file IDs for the element connectivity
250  // w/out actually creating any elements in MOAB.
251  ErrorCode read_elems( int index, const Range& element_file_ids, Range& node_file_ids );
252 
253  // Scan all elements in group. For each element for which all vertices
254  // are contained in idMap (class member), read the element. All new
255  // elements are added to idMap.
256  //
257  // NOTE: Collective IO calls in parallel.
258  ErrorCode read_node_adj_elems( const mhdf_ElemDesc& group, Range* read_entities = 0 );
259 
260  // Scan all elements in specified file table. For each element for
261  // which all vertices are contained in idMap (class member), read the
262  // element. All new elements are added to idMap.
263  //
264  // NOTE: Collective IO calls in parallel.
265  ErrorCode read_node_adj_elems( const mhdf_ElemDesc& group, hid_t connectivity_handle, Range* read_entities = 0 );
266 
267  //! Read poly(gons|hedra)
268  ErrorCode read_poly( const mhdf_ElemDesc& elems, const Range& file_ids );
269 
270  //! Clean up elements that were a) read because we had read all of the
271  //! nodes and b) weren't actually sides of the top-dimension elements
272  //! we were trying to read.
273  ErrorCode delete_non_side_elements( const Range& side_ents );
274 
275  //! Read sets
276  ErrorCode read_sets( const Range& set_file_ids );
277 
278  ErrorCode read_adjacencies( hid_t adjacency_table, long table_length );
279 
280  //! Create tag and read all data.
281  ErrorCode read_tag( int index );
282 
283  //! Create new tag or verify type matches existing tag
284  ErrorCode create_tag( const mhdf_TagDesc& info, Tag& handle, hid_t& type );
285 
286  //! Read dense tag for all entities
287  ErrorCode read_dense_tag( Tag tag_handle,
288  const char* ent_name,
289  hid_t hdf_read_type,
290  hid_t data_table,
291  long start_id,
292  long count );
293 
294  //! Read sparse tag for all entities.
295  ErrorCode read_sparse_tag( Tag tag_handle,
296  hid_t hdf_read_type,
297  hid_t ent_table,
298  hid_t val_table,
299  long num_entities );
300 
301  //! Read variable-length tag for all entities.
302  ErrorCode read_var_len_tag( Tag tag_handle,
303  hid_t hdf_read_type,
304  hid_t ent_table,
305  hid_t val_table,
306  hid_t off_table,
307  long num_entities,
308  long num_values );
309 
310  /**\brief Read index table for sparse tag.
311  *
312  * Read ID table for a sparse or variable-length tag, returning
313  * the handles and offsets within the table for each file ID
314  * that corresponds to an entity we've read from the file (an
315  * entity that is in \c idMap).
316  *
317  * \param id_table The MOAB handle for the tag
318  * \param start_offset Some non-zero value because ranges (in this case
319  * the offset_range) cannot contain zeros.
320  * \param offset_range Output: The offsets in the id table for which IDs
321  * that occur in \c idMap were found. All values
322  * are increased by \c start_offset to avoid
323  * putting zeros in the range.
324  * \param handle_range Output: For each valid ID read from the table,
325  * the corresponding entity handle. Note: if
326  * the IDs did not occur in handle order, then
327  * this will be empty. Use \c handle_vect instead.
328  * \param handle_vect Output: For each valid ID read from the table,
329  * the corresponding entity handle. Note: if
330  * the IDs occurred in handle order, then
331  * this will be empty. Use \c handle_range instead.
332  */
333  ErrorCode read_sparse_tag_indices( const char* name,
334  hid_t id_table,
335  EntityHandle start_offset,
336  Range& offset_range,
337  Range& handle_range,
338  std::vector< EntityHandle >& handle_vect );
339 
340  ErrorCode read_qa( EntityHandle file_set );
341 
342  public:
343  ErrorCode convert_id_to_handle( EntityHandle* in_out_array, size_t array_length );
344 
345  void convert_id_to_handle( EntityHandle* in_out_array, size_t array_length, size_t& array_length_out ) const
346  {
347  return convert_id_to_handle( in_out_array, array_length, array_length_out, idMap );
348  }
349 
350  ErrorCode convert_range_to_handle( const EntityHandle* ranges, size_t num_ranges, Range& merge );
351 
352  static void convert_id_to_handle( EntityHandle* in_out_array,
353  size_t array_length,
354  const RangeMap< long, EntityHandle >& id_map );
355 
356  static void convert_id_to_handle( EntityHandle* in_out_array,
357  size_t array_length,
358  size_t& array_length_out,
359  const RangeMap< long, EntityHandle >& id_map );
360 
361  static void convert_range_to_handle( const EntityHandle* ranges,
362  size_t num_ranges,
363  const RangeMap< long, EntityHandle >& id_map,
364  Range& merge );
365 
366  ErrorCode insert_in_id_map( const Range& file_ids, EntityHandle start_id );
367 
368  ErrorCode insert_in_id_map( long file_id, EntityHandle handle );
369 
370  private:
371  /**\brief Search for entities with specified tag values
372  *
373  *\NOTE For parallel reads, this function does collective IO.
374  *
375  *\param tag_index Index into info->tags specifying which tag to search.
376  *\param sorted_values List of tag values to check for, in ascending sorted
377  * order.
378  *\param file_ids_out File IDs for entities with specified tag values.
379  */
380  ErrorCode search_tag_values( int tag_index,
381  const std::vector< int >& sorted_values,
382  Range& file_ids_out,
383  bool sets_only = false );
384 
385  /**\brief Search for entities with specified tag
386  *
387  *\NOTE For parallel reads, this function does collective IO.
388  *
389  *\param tag_index Index into info->tags specifying which tag to search.
390  *\param file_ids_out File IDs for entities with specified tag values.
391  */
392  ErrorCode get_tagged_entities( int tag_index, Range& file_ids_out );
393 
394  /**\brief Search a table of tag data for a specified set of values.
395  *
396  * Search a table of tag values, returning the indices into the table
397  * at which matches were found.
398  *\NOTE For parallel reads, this function does collective IO.
399  *
400  *\param info Summary of data contained in file.
401  *\param tag_table HDF5/mhdf handle for tag values
402  *\param table_size Number of values in table
403  *\param sorted_values Sorted list of values to search for.
404  *\param value_indices Output: Offsets into the table of data at which
405  * matching values were found.
406  */
407  ErrorCode search_tag_values( hid_t tag_table,
408  unsigned long table_size,
409  const std::vector< int >& sorted_values,
410  std::vector< EntityHandle >& value_indices );
411 
412  /**\brief Get the file IDs for nodes and elements contained in sets.
413  *
414  * Read the contents for the specified sets and return the file IDs
415  * of all nodes and elements contained within those sets.
416  *\param sets Container of file IDs designating entity sets.
417  *\param file_ids Output: File IDs of entities contained in sets.
418  */
419  ErrorCode get_set_contents( const Range& sets, Range& file_ids );
420 
421  /** Given a list of file IDs for entity sets, find all contained
422  * or child sets (at any depth) and append them to the Range
423  * of file IDs.
424  */
425  ErrorCode read_set_ids_recursive( Range& sets_in_out, bool containted_sets, bool child_sets );
426 
427  /** Find all sets containing one or more entities read from the file
428  * and added to idMap
429  */
430  ErrorCode find_sets_containing( Range& sets_out, bool read_set_containing_parents );
431 
432  /**\brief Read sets from file into MOAB for partial read of file.
433  *
434  * Given the file IDs for entity sets (sets_in) and elements and
435  * nodes (id_map), read in all sets containing any of the elements
436  * or nodes and all sets that are (recursively) children of any
437  * other set to be read (those in sets_in or those containing any
438  * already-read element or node.)
439  *\param sets_in File IDs for sets to read (unconditionally)
440  */
441  ErrorCode read_sets_partial( const Range& sets_in );
442 
443  /** Find file IDs of sets containing any entities in the passed id_map */
444  ErrorCode find_sets_containing( hid_t content_handle,
445  hid_t content_type,
446  long content_len,
447  bool read_set_containing_parents,
448  Range& file_ids );
449 
450  public:
451  enum SetMode
452  {
453  CONTENT = 0,
454  CHILD = 1,
455  PARENT = 2
456  };
457 
458  private:
459  // Read the set data specified by by which_data.
460  // Update set data in MOAB according to which_data,
461  // unless file_ids_out is non-null. If file_ids_out is
462  // non-null, then return the file IDs in the passed
463  // range and do not make any changes to MOAB data
464  // structures. If file_ids_out is NULL, then set_start_handle
465  // is ignored.
466  ErrorCode read_set_data( const Range& set_file_ids,
467  EntityHandle set_start_handle,
468  ReadHDF5Dataset& set_data_set,
469  SetMode which_data,
470  Range* file_ids_out = 0 );
471 
472  /**\brief Store file IDS in tag values
473  *
474  * Copy file ID from IDMap for each entity read from file
475  * into a tag value on the entity.
476  */
478 
479  /**\brief Store sets file IDS in a custom tag
480  *
481  * Copy sets file ID from IDMap for each set read from file
482  * into a custom tag on the sets
483  * needed now for the VisIt plugin, to identify sets read
484  */
486 
487  /**\brief Find index in mhdf_FileDesc* fileInfo for specified tag name
488  *
489  * Given a tag name, find its index in fileInfo and verify that
490  * each tag value is a single integer.
491  */
492  ErrorCode find_int_tag( const char* name, int& index_out );
493 
494  void debug_barrier_line( int lineno );
495 };
496 
497 } // namespace moab
498 
499 #endif