Branch data Line data Source code
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 <stdlib.h>
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 : :
57 : : ReadHDF5( Interface* iface );
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, const EntityHandle* file_set, const FileOptions& opts,
67 : : const SubsetList* subset_list = 0, const Tag* file_id_tag = 0 );
68 : :
69 : : ErrorCode read_tag_values( const char* file_name, const char* tag_name, const FileOptions& opts,
70 : : std::vector< int >& tag_values_out, const SubsetList* subset_list = 0 );
71 : 3228 : Interface* moab() const
72 : : {
73 : 3228 : return iFace;
74 : : }
75 : :
76 : : //! Store old HDF5 error handling function
77 : : struct HDF5ErrorHandler
78 : : {
79 : : HDF5_Error_Func_Type func;
80 : : void* data;
81 : : };
82 : :
83 : : protected:
84 : : ErrorCode load_file_impl( const FileOptions& opts );
85 : :
86 : : ErrorCode load_file_partial( const ReaderIface::IDTag* subset_list, int subset_list_length, int num_parts,
87 : : int part_number, const FileOptions& opts );
88 : :
89 : : ErrorCode read_tag_values_all( int tag_index, std::vector< int >& results );
90 : : ErrorCode read_tag_values_partial( int tag_index, const Range& file_ids, std::vector< int >& results );
91 : :
92 : : enum ReadTimingValues
93 : : {
94 : : TOTAL_TIME = 0,
95 : : SET_META_TIME,
96 : : SUBSET_IDS_TIME,
97 : : GET_PARTITION_TIME,
98 : : GET_SET_IDS_TIME,
99 : : GET_SET_CONTENTS_TIME,
100 : : GET_POLYHEDRA_TIME,
101 : : GET_ELEMENTS_TIME,
102 : : GET_NODES_TIME,
103 : : GET_NODEADJ_TIME,
104 : : GET_SIDEELEM_TIME,
105 : : UPDATECONN_TIME,
106 : : ADJACENCY_TIME,
107 : : DELETE_NON_SIDEELEM_TIME,
108 : : READ_SET_IDS_RECURS_TIME,
109 : : FIND_SETS_CONTAINING_TIME,
110 : : READ_SETS_TIME,
111 : : READ_TAGS_TIME,
112 : : STORE_FILE_IDS_TIME,
113 : : READ_QA_TIME,
114 : : NUM_TIMES
115 : : };
116 : :
117 : : void print_times();
118 : :
119 : : private:
120 : : ErrorCode init();
121 : :
122 : 1792 : inline int is_error( mhdf_Status& status )
123 : : {
124 : : int i;
125 [ + + ][ + - ]: 1792 : if( ( i = mhdf_isError( &status ) ) ) MB_SET_ERR_CONT( mhdf_message( &status ) );
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ]
126 : 1792 : return i;
127 : : }
128 : :
129 : : //! The size of the data buffer (<code>dataBuffer</code>).
130 : : int bufferSize;
131 : : //! A memory buffer to use for all I/O operations.
132 : : char* dataBuffer;
133 : :
134 : : //! Interface pointer passed to constructor
135 : : Interface* iFace;
136 : :
137 : : //! The file handle from the mhdf library
138 : : mhdf_FileHandle filePtr;
139 : :
140 : : //! File summary
141 : : mhdf_FileDesc* fileInfo;
142 : :
143 : : //! Map from File ID to MOAB handle
144 : : typedef RangeMap< long, EntityHandle > IDMap;
145 : : IDMap idMap;
146 : :
147 : : //! Cache pointer to read util
148 : : ReadUtilIface* readUtil;
149 : :
150 : : //! The type of an EntityHandle
151 : : hid_t handleType;
152 : :
153 : : //! List of connectivity arrays for which conversion from file ID
154 : : //! to handle was deferred until later.
155 : : struct IDConnectivity
156 : : {
157 : : EntityHandle handle; // Start_handle
158 : : size_t count; // Num entities
159 : : int nodes_per_elem; // Per-element connectivity length
160 : : EntityHandle* array; // Connectivity array
161 : : };
162 : : //! List of connectivity arrays for which conversion from file ID
163 : : //! to handle was deferred until later.
164 : : std::vector< IDConnectivity > idConnectivityList;
165 : :
166 : : //! Read/write property handle
167 : : //! indepIO -> independent IO during true parallel read
168 : : //! collIO -> collective IO during true parallel read
169 : : //! Both are H5P_DEFAULT for serial IO and collective
170 : : //! when reading the entire file on all processors.
171 : : hid_t indepIO, collIO;
172 : :
173 : : ParallelComm* myPcomm;
174 : :
175 : : //! Use IODebugTrack instances to verify reads.
176 : : //! Enable with the DEBUG_OVERLAPS option.
177 : : bool debugTrack;
178 : : //! Debug output. Verbosity controlled with DEBUG_FORMAT option.
179 : : DebugOutput dbgOut;
180 : : //! Doing true parallel read (PARALLEL=READ_PART)
181 : : bool nativeParallel;
182 : : //! MPI_Comm value (unused if \c !nativeParallel)
183 : : Comm* mpiComm;
184 : :
185 : : //! Flags for some behavior that can be changed through
186 : : //! reader options
187 : : bool blockedCoordinateIO;
188 : : bool bcastSummary;
189 : : bool bcastDuplicateReads;
190 : :
191 : : //! Store old HDF5 error handling function
192 : : HDF5ErrorHandler errorHandler;
193 : :
194 : : long ( *setMeta )[4];
195 : :
196 : : double _times[NUM_TIMES];
197 : : CpuTimer* timer;
198 : : bool cputime;
199 : : ErrorCode read_all_set_meta();
200 : :
201 : : ErrorCode set_up_read( const char* file_name, const FileOptions& opts );
202 : : ErrorCode clean_up_read( const FileOptions& opts );
203 : :
204 : : //! Given a list of tags and values, get the file ids for the
205 : : //! corresponding entities in the file.
206 : : ErrorCode get_subset_ids( const ReaderIface::IDTag* subset_list, int subset_list_length, Range& file_ids_out );
207 : :
208 : : /**\brief Remove all but the specified fraction of sets from the passed range
209 : : *
210 : : * Select a subset of the gathered set of file ids to read in based on
211 : : * communicator size and rank.
212 : : *\param tmp_file_ids As input: sets to be read on all procs.
213 : : * As output: sets to read on this proc.
214 : : *\param num_parts communicator size
215 : : *\param part_number communicator rank
216 : : */
217 : : ErrorCode get_partition( Range& tmp_file_ids, int num_parts, int part_number );
218 : :
219 : : ErrorCode read_nodes( const Range& node_file_ids );
220 : :
221 : : // Read elements in fileInfo->elems[index]
222 : : ErrorCode read_elems( int index );
223 : :
224 : : // Read subset of elements in fileInfo->elems[index]
225 : : ErrorCode read_elems( int index, const Range& file_ids, Range* node_ids = 0 );
226 : :
227 : : //! Read element connectivity.
228 : : //!
229 : : //!\param node_ids If this is non-null, the union of the connectivity list
230 : : //! for all elements is passed back as FILE IDS in this
231 : : //! range AND the connectivity list is left in the form
232 : : //! of file IDs (NOT NODE HANDLES).
233 : : ErrorCode read_elems( const mhdf_ElemDesc& elems, const Range& file_ids, Range* node_ids = 0 );
234 : :
235 : : //! Update connectivity data for all element groups for which read_elems
236 : : //! was called with a non-null \c node_ids argument.
237 : : ErrorCode update_connectivity();
238 : :
239 : : // Read connectivity data for a list of element file ids.
240 : : // passing back the file IDs for the element connectivity
241 : : // w/out actually creating any elements in MOAB.
242 : : ErrorCode read_elems( int index, const Range& element_file_ids, Range& node_file_ids );
243 : :
244 : : // Scan all elements in group. For each element for which all vertices
245 : : // are contained in idMap (class member), read the element. All new
246 : : // elements are added to idMap.
247 : : //
248 : : // NOTE: Collective IO calls in parallel.
249 : : ErrorCode read_node_adj_elems( const mhdf_ElemDesc& group, Range* read_entities = 0 );
250 : :
251 : : // Scan all elements in specified file table. For each element for
252 : : // which all vertices are contained in idMap (class member), read the
253 : : // element. All new elements are added to idMap.
254 : : //
255 : : // NOTE: Collective IO calls in parallel.
256 : : ErrorCode read_node_adj_elems( const mhdf_ElemDesc& group, hid_t connectivity_handle, Range* read_entities = 0 );
257 : :
258 : : //! Read poly(gons|hedra)
259 : : ErrorCode read_poly( const mhdf_ElemDesc& elems, const Range& file_ids );
260 : :
261 : : //! Clean up elements that were a) read because we had read all of the
262 : : //! nodes and b) weren't actually sides of the top-dimension elements
263 : : //! we were trying to read.
264 : : ErrorCode delete_non_side_elements( const Range& side_ents );
265 : :
266 : : //! Read sets
267 : : ErrorCode read_sets( const Range& set_file_ids );
268 : :
269 : : ErrorCode read_adjacencies( hid_t adjacency_table, long table_length );
270 : :
271 : : //! Create tag and read all data.
272 : : ErrorCode read_tag( int index );
273 : :
274 : : //! Create new tag or verify type matches existing tag
275 : : ErrorCode create_tag( const mhdf_TagDesc& info, Tag& handle, hid_t& type );
276 : :
277 : : //! Read dense tag for all entities
278 : : ErrorCode read_dense_tag( Tag tag_handle, const char* ent_name, hid_t hdf_read_type, hid_t data_table,
279 : : long start_id, long count );
280 : :
281 : : //! Read sparse tag for all entities.
282 : : ErrorCode read_sparse_tag( Tag tag_handle, hid_t hdf_read_type, hid_t ent_table, hid_t val_table,
283 : : long num_entities );
284 : :
285 : : //! Read variable-length tag for all entities.
286 : : 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,
287 : : long num_entities, long num_values );
288 : :
289 : : /**\brief Read index table for sparse tag.
290 : : *
291 : : * Read ID table for a sparse or variable-length tag, returning
292 : : * the handles and offsets within the table for each file ID
293 : : * that corresponds to an entity we've read from the file (an
294 : : * entity that is in \c idMap).
295 : : *
296 : : * \param id_table The MOAB handle for the tag
297 : : * \param start_offset Some non-zero value because ranges (in this case
298 : : * the offset_range) cannot contain zeros.
299 : : * \param offset_range Output: The offsets in the id table for which IDs
300 : : * that occur in \c idMap were found. All values
301 : : * are increased by \c start_offset to avoid
302 : : * putting zeros in the range.
303 : : * \param handle_range Output: For each valid ID read from the table,
304 : : * the corresponding entity handle. Note: if
305 : : * the IDs did not occur in handle order, then
306 : : * this will be empty. Use \c handle_vect instead.
307 : : * \param handle_vect Output: For each valid ID read from the table,
308 : : * the corresponding entity handle. Note: if
309 : : * the IDs occurred in handle order, then
310 : : * this will be empty. Use \c handle_range instead.
311 : : */
312 : : ErrorCode read_sparse_tag_indices( const char* name, hid_t id_table, EntityHandle start_offset, Range& offset_range,
313 : : Range& handle_range, std::vector< EntityHandle >& handle_vect );
314 : :
315 : : ErrorCode read_qa( EntityHandle file_set );
316 : :
317 : : public:
318 : : ErrorCode convert_id_to_handle( EntityHandle* in_out_array, size_t array_length );
319 : :
320 : 2365 : void convert_id_to_handle( EntityHandle* in_out_array, size_t array_length, size_t& array_length_out ) const
321 : : {
322 : 2365 : return convert_id_to_handle( in_out_array, array_length, array_length_out, idMap );
323 : : }
324 : :
325 : : ErrorCode convert_range_to_handle( const EntityHandle* ranges, size_t num_ranges, Range& merge );
326 : :
327 : : static void convert_id_to_handle( EntityHandle* in_out_array, size_t array_length,
328 : : const RangeMap< long, EntityHandle >& id_map );
329 : :
330 : : static void convert_id_to_handle( EntityHandle* in_out_array, size_t array_length, size_t& array_length_out,
331 : : const RangeMap< long, EntityHandle >& id_map );
332 : :
333 : : static void convert_range_to_handle( const EntityHandle* ranges, size_t num_ranges,
334 : : const RangeMap< long, EntityHandle >& id_map, Range& merge );
335 : :
336 : : ErrorCode insert_in_id_map( const Range& file_ids, EntityHandle start_id );
337 : :
338 : : ErrorCode insert_in_id_map( long file_id, EntityHandle handle );
339 : :
340 : : private:
341 : : /**\brief Search for entities with specified tag values
342 : : *
343 : : *\NOTE For parallel reads, this function does collective IO.
344 : : *
345 : : *\param tag_index Index into info->tags specifying which tag to search.
346 : : *\param sorted_values List of tag values to check for, in ascending sorted
347 : : * order.
348 : : *\param file_ids_out File IDs for entities with specified tag values.
349 : : */
350 : : ErrorCode search_tag_values( int tag_index, const std::vector< int >& sorted_values, Range& file_ids_out,
351 : : bool sets_only = false );
352 : :
353 : : /**\brief Search for entities with specified tag
354 : : *
355 : : *\NOTE For parallel reads, this function does collective IO.
356 : : *
357 : : *\param tag_index Index into info->tags specifying which tag to search.
358 : : *\param file_ids_out File IDs for entities with specified tag values.
359 : : */
360 : : ErrorCode get_tagged_entities( int tag_index, Range& file_ids_out );
361 : :
362 : : /**\brief Search a table of tag data for a specified set of values.
363 : : *
364 : : * Search a table of tag values, returning the indices into the table
365 : : * at which matches were found.
366 : : *\NOTE For parallel reads, this function does collective IO.
367 : : *
368 : : *\param info Summary of data contained in file.
369 : : *\param tag_table HDF5/mhdf handle for tag values
370 : : *\param table_size Number of values in table
371 : : *\param sorted_values Sorted list of values to search for.
372 : : *\param value_indices Output: Offsets into the table of data at which
373 : : * matching values were found.
374 : : */
375 : : ErrorCode search_tag_values( hid_t tag_table, unsigned long table_size, const std::vector< int >& sorted_values,
376 : : std::vector< EntityHandle >& value_indices );
377 : :
378 : : /**\brief Get the file IDs for nodes and elements contained in sets.
379 : : *
380 : : * Read the contents for the specified sets and return the file IDs
381 : : * of all nodes and elements contained within those sets.
382 : : *\param sets Container of file IDs designating entity sets.
383 : : *\param file_ids Output: File IDs of entities contained in sets.
384 : : */
385 : : ErrorCode get_set_contents( const Range& sets, Range& file_ids );
386 : :
387 : : /** Given a list of file IDs for entity sets, find all contained
388 : : * or child sets (at any depth) and append them to the Range
389 : : * of file IDs.
390 : : */
391 : : ErrorCode read_set_ids_recursive( Range& sets_in_out, bool containted_sets, bool child_sets );
392 : :
393 : : /** Find all sets containing one or more entities read from the file
394 : : * and added to idMap
395 : : */
396 : : ErrorCode find_sets_containing( Range& sets_out, bool read_set_containing_parents );
397 : :
398 : : /**\brief Read sets from file into MOAB for partial read of file.
399 : : *
400 : : * Given the file IDs for entity sets (sets_in) and elements and
401 : : * nodes (id_map), read in all sets containing any of the elements
402 : : * or nodes and all sets that are (recursively) children of any
403 : : * other set to be read (those in sets_in or those containing any
404 : : * already-read element or node.)
405 : : *\param sets_in File IDs for sets to read (unconditionally)
406 : : */
407 : : ErrorCode read_sets_partial( const Range& sets_in );
408 : :
409 : : /** Find file IDs of sets containing any entities in the passed id_map */
410 : : ErrorCode find_sets_containing( hid_t content_handle, hid_t content_type, long content_len,
411 : : bool read_set_containing_parents, Range& file_ids );
412 : :
413 : : public:
414 : : enum SetMode
415 : : {
416 : : CONTENT = 0,
417 : : CHILD = 1,
418 : : PARENT = 2
419 : : };
420 : :
421 : : private:
422 : : // Read the set data specified by by which_data.
423 : : // Update set data in MOAB according to which_data,
424 : : // unless file_ids_out is non-null. If file_ids_out is
425 : : // non-null, then return the file IDs in the passed
426 : : // range and do not make any changes to MOAB data
427 : : // structures. If file_ids_out is NULL, then set_start_handle
428 : : // is ignored.
429 : : ErrorCode read_set_data( const Range& set_file_ids, EntityHandle set_start_handle, ReadHDF5Dataset& set_data_set,
430 : : SetMode which_data, Range* file_ids_out = 0 );
431 : :
432 : : /**\brief Store file IDS in tag values
433 : : *
434 : : * Copy file ID from IDMap for each entity read from file
435 : : * into a tag value on the entity.
436 : : */
437 : : ErrorCode store_file_ids( Tag tag );
438 : :
439 : : /**\brief Store sets file IDS in a custom tag
440 : : *
441 : : * Copy sets file ID from IDMap for each set read from file
442 : : * into a custom tag on the sets
443 : : * needed now for the VisIt plugin, to identify sets read
444 : : */
445 : : ErrorCode store_sets_file_ids();
446 : :
447 : : /**\brief Find index in mhdf_FileDesc* fileInfo for specified tag name
448 : : *
449 : : * Given a tag name, find its index in fileInfo and verify that
450 : : * each tag value is a single integer.
451 : : */
452 : : ErrorCode find_int_tag( const char* name, int& index_out );
453 : :
454 : : void debug_barrier_line( int lineno );
455 : : };
456 : :
457 : : } // namespace moab
458 : :
459 : : #endif
|