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 : : //-------------------------------------------------------------------------
17 : : // Filename : WriteHDF5.cpp
18 : : //
19 : : // Purpose : TSTT HDF5 Writer
20 : : //
21 : : // Special Notes : WriteSLAC used as template for this
22 : : //
23 : : // Creator : Jason Kraftcheck
24 : : //
25 : : // Creation Date : 04/01/04
26 : : //-------------------------------------------------------------------------
27 : :
28 : : #include <assert.h>
29 : : #if defined( _WIN32 )
30 : : typedef int id_t;
31 : : #elif defined( __MINGW32__ )
32 : : #include <sys/time.h>
33 : : #endif
34 : : #include <time.h>
35 : : #include <stdlib.h>
36 : : #include <string.h>
37 : : #include <stdarg.h>
38 : : #include <limits>
39 : : #include <cstdio>
40 : : #include <iostream>
41 : : #include "WriteHDF5.hpp"
42 : : #include <H5Tpublic.h>
43 : : #include <H5Ppublic.h>
44 : : #include <H5Epublic.h>
45 : : #include "moab/Interface.hpp"
46 : : #include "Internals.hpp"
47 : : #include "MBTagConventions.hpp"
48 : : #include "moab/CN.hpp"
49 : : #include "moab/FileOptions.hpp"
50 : : #include "moab/CpuTimer.hpp"
51 : : #include "IODebugTrack.hpp"
52 : : #include "mhdf.h"
53 : :
54 : : #ifndef MOAB_HAVE_HDF5
55 : : #error Attempt to compile WriteHDF5 with HDF5 support disabled
56 : : #endif
57 : :
58 : : #undef BLOCKED_COORD_IO
59 : :
60 : : #ifdef MOAB_HAVE_VALGRIND
61 : : #include <valgrind/memcheck.h>
62 : : #else
63 : : #ifndef VALGRIND_CHECK_MEM_IS_DEFINED
64 : : #define VALGRIND_CHECK_MEM_IS_DEFINED( a, b ) ( (void)0 )
65 : : #endif
66 : : #ifndef VALGRIND_CHECK_MEM_IS_ADDRESSABLE
67 : : #define VALGRIND_CHECK_MEM_IS_ADDRESSABLE( a, b ) ( (void)0 )
68 : : #endif
69 : : #ifndef VALGRIND_MAKE_MEM_UNDEFINED
70 : : #define VALGRIND_MAKE_MEM_UNDEFINED( a, b ) ( (void)0 )
71 : : #endif
72 : : #endif
73 : :
74 : : namespace moab
75 : : {
76 : :
77 : : template < typename T >
78 : : inline void VALGRIND_MAKE_VEC_UNDEFINED( std::vector< T >& v )
79 : : {
80 : : (void)VALGRIND_MAKE_MEM_UNDEFINED( (T*)&v[0], v.size() * sizeof( T ) );
81 : : }
82 : :
83 : : #define WRITE_HDF5_BUFFER_SIZE ( 40 * 1024 * 1024 )
84 : :
85 : 114 : static hid_t get_id_type()
86 : : {
87 : : if( 8 == sizeof( WriteHDF5::wid_t ) )
88 : : {
89 : : if( 8 == sizeof( long ) )
90 : 57 : return H5T_NATIVE_ULONG;
91 : : else
92 : : return H5T_NATIVE_UINT64;
93 : : }
94 : : else if( 4 == sizeof( WriteHDF5::wid_t ) )
95 : : {
96 : : if( 4 == sizeof( int ) )
97 : : return H5T_NATIVE_UINT;
98 : : else
99 : : return H5T_NATIVE_UINT32;
100 : : }
101 : : else
102 : : {
103 : : assert( 0 );
104 : : return (hid_t)-1;
105 : : }
106 : : }
107 : :
108 : : // This is the HDF5 type used to store file IDs
109 : 57 : const hid_t WriteHDF5::id_type = get_id_type();
110 : :
111 : : // This function doesn't do anything useful. It's just a nice
112 : : // place to set a break point to determine why the writer fails.
113 : 0 : static inline ErrorCode error( ErrorCode rval )
114 : : {
115 : 0 : return rval;
116 : : }
117 : :
118 : : // Call \c error function during HDF5 library errors to make
119 : : // it easier to trap such errors in the debugger. This function
120 : : // gets registered with the HDF5 library as a callback. It
121 : : // works the same as the default (H5Eprint), except that it
122 : : // also calls the \c error function as a no-op.
123 : : #if defined( H5E_auto_t_vers ) && H5E_auto_t_vers > 1
124 : 0 : static herr_t handle_hdf5_error( hid_t stack, void* data )
125 : : {
126 : 0 : WriteHDF5::HDF5ErrorHandler* h = reinterpret_cast< WriteHDF5::HDF5ErrorHandler* >( data );
127 : 0 : herr_t result = 0;
128 [ # # ]: 0 : if( h->func ) result = ( *h->func )( stack, h->data );
129 : 0 : error( MB_FAILURE );
130 : 0 : return result;
131 : : }
132 : : #else
133 : : static herr_t handle_hdf5_error( void* data )
134 : : {
135 : : WriteHDF5::HDF5ErrorHandler* h = reinterpret_cast< WriteHDF5::HDF5ErrorHandler* >( data );
136 : : herr_t result = 0;
137 : : if( h->func ) result = ( *h->func )( h->data );
138 : : error( MB_FAILURE );
139 : : return result;
140 : : }
141 : : #endif
142 : :
143 : : // Some macros to handle error checking. The
144 : : // CHK_MHDF__ERR* macros check the value of an mhdf_Status
145 : : // object. The CHK_MB_ERR_* check the value of an ErrorCode.
146 : : // The *_0 macros accept no other arguments. The *_1
147 : : // macros accept a single hdf5 handle to close on error.
148 : : // The *_2 macros accept an array of two hdf5 handles to
149 : : // close on error. The _*2C macros accept one hdf5 handle
150 : : // to close on error and a bool and an hdf5 handle where
151 : : // the latter handle is conditionally closed depending on
152 : : // the value of the bool. All macros contain a "return"
153 : : // statement.
154 : : #define CHK_MHDF_ERR_0( A ) \
155 : : do \
156 : : { \
157 : : if( mhdf_isError( &( A ) ) ) \
158 : : { \
159 : : MB_SET_ERR_CONT( mhdf_message( &( A ) ) ); \
160 : : assert( 0 ); \
161 : : return error( MB_FAILURE ); \
162 : : } \
163 : : } while( false )
164 : :
165 : : #define CHK_MHDF_ERR_1( A, B ) \
166 : : do \
167 : : { \
168 : : if( mhdf_isError( &( A ) ) ) \
169 : : { \
170 : : MB_SET_ERR_CONT( mhdf_message( &( A ) ) ); \
171 : : assert( 0 ); \
172 : : mhdf_closeData( filePtr, ( B ), &( A ) ); \
173 : : return error( MB_FAILURE ); \
174 : : } \
175 : : } while( false )
176 : :
177 : : #define CHK_MHDF_ERR_2( A, B ) \
178 : : do \
179 : : { \
180 : : if( mhdf_isError( &( A ) ) ) \
181 : : { \
182 : : MB_SET_ERR_CONT( mhdf_message( &( A ) ) ); \
183 : : assert( 0 ); \
184 : : mhdf_closeData( filePtr, ( B )[0], &( A ) ); \
185 : : mhdf_closeData( filePtr, ( B )[1], &( A ) ); \
186 : : return error( MB_FAILURE ); \
187 : : } \
188 : : } while( false )
189 : :
190 : : #define CHK_MHDF_ERR_3( A, B ) \
191 : : do \
192 : : { \
193 : : if( mhdf_isError( &( A ) ) ) \
194 : : { \
195 : : MB_SET_ERR_CONT( mhdf_message( &( A ) ) ); \
196 : : assert( 0 ); \
197 : : mhdf_closeData( filePtr, ( B )[0], &( A ) ); \
198 : : mhdf_closeData( filePtr, ( B )[1], &( A ) ); \
199 : : mhdf_closeData( filePtr, ( B )[2], &( A ) ); \
200 : : return error( MB_FAILURE ); \
201 : : } \
202 : : } while( false )
203 : :
204 : : #define CHK_MHDF_ERR_2C( A, B, C, D ) \
205 : : do \
206 : : { \
207 : : if( mhdf_isError( &( A ) ) ) \
208 : : { \
209 : : MB_SET_ERR_CONT( mhdf_message( &( A ) ) ); \
210 : : assert( 0 ); \
211 : : mhdf_closeData( filePtr, ( B ), &( A ) ); \
212 : : if( C ) mhdf_closeData( filePtr, ( D ), &( A ) ); \
213 : : return error( MB_FAILURE ); \
214 : : } \
215 : : } while( false )
216 : :
217 : : #define CHK_MB_ERR_0( A ) \
218 : : do \
219 : : { \
220 : : if( MB_SUCCESS != ( A ) ) \
221 : : { \
222 : : MB_CHK_ERR_CONT( ( A ) ); \
223 : : return error( A ); \
224 : : } \
225 : : } while( false )
226 : :
227 : : #define CHK_MB_ERR_1( A, B, C ) \
228 : : do \
229 : : { \
230 : : if( MB_SUCCESS != ( A ) ) \
231 : : { \
232 : : MB_CHK_ERR_CONT( ( A ) ); \
233 : : mhdf_closeData( filePtr, ( B ), &( C ) ); \
234 : : assert( 0 ); \
235 : : return error( A ); \
236 : : } \
237 : : } while( false )
238 : :
239 : : #define CHK_MB_ERR_2( A, B, C ) \
240 : : do \
241 : : { \
242 : : if( MB_SUCCESS != ( A ) ) \
243 : : { \
244 : : MB_CHK_ERR_CONT( ( A ) ); \
245 : : mhdf_closeData( filePtr, ( B )[0], &( C ) ); \
246 : : mhdf_closeData( filePtr, ( B )[1], &( C ) ); \
247 : : write_finished(); \
248 : : assert( 0 ); \
249 : : return error( A ); \
250 : : } \
251 : : } while( false )
252 : :
253 : : #define CHK_MB_ERR_3( A, B, C ) \
254 : : do \
255 : : { \
256 : : if( MB_SUCCESS != ( A ) ) \
257 : : { \
258 : : MB_CHK_ERR_CONT( ( A ) ); \
259 : : mhdf_closeData( filePtr, ( B )[0], &( C ) ); \
260 : : mhdf_closeData( filePtr, ( B )[1], &( C ) ); \
261 : : mhdf_closeData( filePtr, ( B )[2], &( C ) ); \
262 : : write_finished(); \
263 : : assert( 0 ); \
264 : : return error( A ); \
265 : : } \
266 : : } while( false )
267 : :
268 : : #define CHK_MB_ERR_2C( A, B, C, D, E ) \
269 : : do \
270 : : { \
271 : : if( MB_SUCCESS != ( A ) ) \
272 : : { \
273 : : MB_CHK_ERR_CONT( ( A ) ); \
274 : : mhdf_closeData( filePtr, ( B ), &( E ) ); \
275 : : if( C ) mhdf_closeData( filePtr, ( D ), &( E ) ); \
276 : : write_finished(); \
277 : : assert( 0 ); \
278 : : return error( A ); \
279 : : } \
280 : : } while( false )
281 : :
282 : : #define debug_barrier() debug_barrier_line( __LINE__ )
283 : 820 : void WriteHDF5::debug_barrier_line( int ) {}
284 : :
285 : : class CheckOpenWriteHDF5Handles
286 : : {
287 : : int fileline;
288 : : mhdf_FileHandle handle;
289 : : int enter_count;
290 : :
291 : : public:
292 : 2327 : CheckOpenWriteHDF5Handles( mhdf_FileHandle file, int line )
293 : 2327 : : fileline( line ), handle( file ), enter_count( mhdf_countOpenHandles( file ) )
294 : : {
295 : 2327 : }
296 : :
297 : 2327 : ~CheckOpenWriteHDF5Handles()
298 : : {
299 : 2327 : int new_count = mhdf_countOpenHandles( handle );
300 [ - + ]: 2327 : if( new_count != enter_count )
301 : : {
302 : 0 : std::cout << "Leaked HDF5 object handle in function at " << __FILE__ << ":" << fileline << std::endl
303 : 0 : << "Open at entrance: " << enter_count << std::endl
304 : 0 : << "Open at exit: " << new_count << std::endl;
305 : : }
306 : 2327 : }
307 : : };
308 : :
309 : 57 : MPEState WriteHDF5::topState;
310 : 57 : MPEState WriteHDF5::subState;
311 : :
312 : : #ifdef NDEBUG
313 : : #define CHECK_OPEN_HANDLES
314 : : #else
315 : : #define CHECK_OPEN_HANDLES CheckOpenWriteHDF5Handles check_open_handles_( filePtr, __LINE__ )
316 : : #endif
317 : :
318 : 127 : bool WriteHDF5::convert_handle_tag( const EntityHandle* source, EntityHandle* dest, size_t count ) const
319 : : {
320 : 127 : bool some_valid = false;
321 [ + + ]: 509 : for( size_t i = 0; i < count; ++i )
322 : : {
323 [ + + ]: 382 : if( !source[i] )
324 : 86 : dest[i] = 0;
325 : : else
326 : : {
327 : 296 : dest[i] = idMap.find( source[i] );
328 [ + + ]: 296 : if( dest[i] ) some_valid = true;
329 : : }
330 : : }
331 : :
332 : 127 : return some_valid;
333 : : }
334 : :
335 : 72 : bool WriteHDF5::convert_handle_tag( EntityHandle* data, size_t count ) const
336 : : {
337 : : assert( sizeof( EntityHandle ) == sizeof( wid_t ) );
338 : 36 : return convert_handle_tag( data, data, count );
339 : : }
340 : :
341 : 129 : ErrorCode WriteHDF5::assign_ids( const Range& entities, wid_t id )
342 : : {
343 [ + - ]: 129 : Range::const_pair_iterator pi;
344 [ + - ][ + - ]: 3007 : for( pi = entities.const_pair_begin(); pi != entities.const_pair_end(); ++pi )
[ + - ][ + - ]
[ + + ]
345 : : {
346 [ + - ][ + - ]: 2878 : const EntityHandle n = pi->second - pi->first + 1;
347 : : dbgOut.printf( 3, "Assigning %s %lu to %lu to file IDs [%lu,%lu]\n",
348 [ + - ]: 2878 : CN::EntityTypeName( TYPE_FROM_HANDLE( pi->first ) ),
349 [ + - ][ + - ]: 2878 : (unsigned long)( ID_FROM_HANDLE( pi->first ) ),
350 [ + - ][ + - ]: 2878 : (unsigned long)( ID_FROM_HANDLE( pi->first ) + n - 1 ), (unsigned long)id,
351 [ + - ][ + - ]: 2878 : (unsigned long)( id + n - 1 ) );
[ + - ]
352 [ + - ][ + - ]: 2878 : if( TYPE_FROM_HANDLE( pi->first ) == MBPOLYGON || TYPE_FROM_HANDLE( pi->first ) == MBPOLYHEDRON )
[ + + ][ + - ]
[ + - ][ - + ]
[ + + ]
353 : : {
354 : 3 : int num_vertices = 0;
355 : 3 : const EntityHandle* conn = 0;
356 [ + - ][ + - ]: 3 : iFace->get_connectivity( pi->first, conn, num_vertices );
357 [ + - ]: 3 : dbgOut.printf( 3, " poly with %d verts/faces \n", num_vertices );
358 : : }
359 [ + - ][ + - ]: 2878 : if( !idMap.insert( pi->first, id, n ).second ) return error( MB_FAILURE );
[ - + ]
360 : 2878 : id += n;
361 : : }
362 : :
363 : 129 : return MB_SUCCESS;
364 : : }
365 : :
366 : 950 : const char* WriteHDF5::ExportSet::name() const
367 : : {
368 : : static char buffer[128];
369 [ + + + ]: 950 : switch( type )
370 : : {
371 : : case MBVERTEX:
372 : 180 : return mhdf_node_type_handle();
373 : : case MBENTITYSET:
374 : 160 : return mhdf_set_type_handle();
375 : : default:
376 : 610 : sprintf( buffer, "%s%d", CN::EntityTypeName( type ), num_nodes );
377 : 610 : return buffer;
378 : : }
379 : : }
380 : :
381 : 18 : WriterIface* WriteHDF5::factory( Interface* iface )
382 : : {
383 [ + - ]: 18 : return new WriteHDF5( iface );
384 : : }
385 : :
386 : 39 : WriteHDF5::WriteHDF5( Interface* iface )
387 : : : bufferSize( WRITE_HDF5_BUFFER_SIZE ), dataBuffer( 0 ), iFace( iface ), writeUtil( 0 ), filePtr( 0 ),
388 : : setContentsOffset( 0 ), setChildrenOffset( 0 ), setParentsOffset( 0 ), maxNumSetContents( 0 ),
389 : : maxNumSetChildren( 0 ), maxNumSetParents( 0 ), writeSets( false ), writeSetContents( false ),
390 : : writeSetChildren( false ), writeSetParents( false ), parallelWrite( false ), collectiveIO( false ),
391 [ + - ][ + - ]: 39 : writeTagDense( false ), writeProp( H5P_DEFAULT ), dbgOut( "H5M", stderr ), debugTrack( false )
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
392 : : {
393 : 39 : }
394 : :
395 : 39 : ErrorCode WriteHDF5::init()
396 : : {
397 : : ErrorCode rval;
398 : :
399 [ - + ]: 39 : if( writeUtil ) // init has already been called
400 : 0 : return MB_SUCCESS;
401 : : /*
402 : : #ifdef DEBUG
403 : : H5Eset_auto(&hdf_error_handler, writeUtil); // HDF5 callback for errors
404 : : #endif
405 : : */
406 : : // For known tag types, store the corresponding HDF5 in which
407 : : // the tag data is to be written in the file.
408 : : // register_known_tag_types(iFace);
409 : :
410 : : // Get the util interface
411 : 39 : rval = iFace->query_interface( writeUtil );
412 [ - + ][ # # ]: 39 : CHK_MB_ERR_0( rval );
[ # # ]
413 : :
414 : 39 : idMap.clear();
415 : :
416 : : #if defined( H5Eget_auto_vers ) && H5Eget_auto_vers > 1
417 : 39 : herr_t err = H5Eget_auto( H5E_DEFAULT, &errorHandler.func, &errorHandler.data );
418 : : #else
419 : : herr_t err = H5Eget_auto( &errorHandler.func, &errorHandler.data );
420 : : #endif
421 [ - + ]: 39 : if( err < 0 )
422 : : {
423 : 0 : errorHandler.func = 0;
424 : 0 : errorHandler.data = 0;
425 : : }
426 : : else
427 : : {
428 : : #if defined( H5Eset_auto_vers ) && H5Eset_auto_vers > 1
429 : 39 : err = H5Eset_auto( H5E_DEFAULT, &handle_hdf5_error, &errorHandler );
430 : : #else
431 : : err = H5Eset_auto( &handle_hdf5_error, &errorHandler );
432 : : #endif
433 [ - + ]: 39 : if( err < 0 )
434 : : {
435 : 0 : errorHandler.func = 0;
436 : 0 : errorHandler.data = 0;
437 : : }
438 : : }
439 : :
440 [ + + ]: 39 : if( !topState.valid() ) topState = MPEState( "WriteHDF5", "yellow" );
441 [ + + ]: 39 : if( !subState.valid() ) subState = MPEState( "WriteHDF5 subevent", "cyan" );
442 : :
443 : 39 : return MB_SUCCESS;
444 : : }
445 : :
446 : 39 : ErrorCode WriteHDF5::write_finished()
447 : : {
448 : : // Release memory allocated in lists
449 : 39 : exportList.clear();
450 [ + - ]: 39 : nodeSet.range.clear();
451 [ + - ]: 39 : setSet.range.clear();
452 : 39 : tagList.clear();
453 [ + - ]: 39 : idMap.clear();
454 : :
455 : : HDF5ErrorHandler handler;
456 : : #if defined( H5Eget_auto_vers ) && H5Eget_auto_vers > 1
457 [ + - ]: 39 : herr_t err = H5Eget_auto( H5E_DEFAULT, &handler.func, &handler.data );
458 : : #else
459 : : herr_t err = H5Eget_auto( &handler.func, &handler.data );
460 : : #endif
461 [ + - ][ + - ]: 39 : if( err >= 0 && handler.func == &handle_hdf5_error )
462 : : {
463 [ - + ]: 39 : assert( handler.data == &errorHandler );
464 : : #if defined( H5Eget_auto_vers ) && H5Eget_auto_vers > 1
465 [ + - ]: 39 : H5Eset_auto( H5E_DEFAULT, errorHandler.func, errorHandler.data );
466 : : #else
467 : : H5Eset_auto( errorHandler.func, errorHandler.data );
468 : : #endif
469 : : }
470 : :
471 : 39 : return MB_SUCCESS;
472 : : }
473 : :
474 [ + - ][ + - ]: 96 : WriteHDF5::~WriteHDF5()
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
475 : : {
476 [ - + ]: 39 : if( !writeUtil ) // init() failed.
477 : 0 : return;
478 : :
479 : 39 : iFace->release_interface( writeUtil );
480 [ - + ]: 57 : }
481 : :
482 : 39 : ErrorCode WriteHDF5::write_file( const char* filename, bool overwrite, const FileOptions& opts,
483 : : const EntityHandle* set_array, const int num_sets,
484 : : const std::vector< std::string >& qa_records, const Tag* tag_list, int num_tags,
485 : : int user_dimension )
486 : : {
487 : : mhdf_Status status;
488 : :
489 : 39 : parallelWrite = false;
490 : 39 : collectiveIO = false;
491 : :
492 : : // Enable debug output
493 : 39 : int tmpval = 0;
494 [ + - ][ - + ]: 39 : if( MB_SUCCESS == opts.get_int_option( "DEBUG_IO", 1, tmpval ) ) dbgOut.set_verbosity( tmpval );
[ # # ]
495 : :
496 : : // writeTagDense = (MB_SUCCESS == opts.get_null_option("DENSE_TAGS"));
497 : 39 : writeTagDense = true;
498 : :
499 : : // Enable some extra checks for reads. Note: amongst other things this
500 : : // will print errors if the entire file is not read, so if doing a
501 : : // partial read that is not a parallel read, this should be disabled.
502 [ + - ]: 39 : debugTrack = ( MB_SUCCESS == opts.get_null_option( "DEBUG_BINIO" ) );
503 : :
504 : 39 : bufferSize = WRITE_HDF5_BUFFER_SIZE;
505 : : int buf_size;
506 [ + - ]: 39 : ErrorCode rval = opts.get_int_option( "BUFFER_SIZE", buf_size );
507 [ - + ][ # # ]: 39 : if( MB_SUCCESS == rval && buf_size >= 24 ) bufferSize = buf_size;
508 : :
509 : : // Allocate internal buffer to use when gathering data to write.
510 : 39 : dataBuffer = (char*)malloc( bufferSize );
511 [ - + ]: 39 : if( !dataBuffer ) return error( MB_MEMORY_ALLOCATION_FAILED );
512 : :
513 : : // Clear filePtr so we know if it is open upon failure
514 : 39 : filePtr = 0;
515 : :
516 : : // Do actual write.
517 : 39 : writeProp = H5P_DEFAULT;
518 : : ErrorCode result = write_file_impl( filename, overwrite, opts, set_array, num_sets, qa_records, tag_list, num_tags,
519 [ + - ]: 39 : user_dimension );
520 : : // Close writeProp if it was opened
521 [ - + ][ # # ]: 39 : if( writeProp != H5P_DEFAULT ) H5Pclose( writeProp );
522 : :
523 : : // Free memory buffer
524 : 39 : free( dataBuffer );
525 : 39 : dataBuffer = 0;
526 : :
527 : : // Close file
528 : 39 : bool created_file = false;
529 [ + - ]: 39 : if( filePtr )
530 : : {
531 : 39 : created_file = true;
532 [ + - ]: 39 : mhdf_closeFile( filePtr, &status );
533 : 39 : filePtr = 0;
534 [ + - ][ - + ]: 39 : if( mhdf_isError( &status ) )
535 : : {
536 [ # # ][ # # ]: 0 : MB_SET_ERR_CONT( mhdf_message( &status ) );
[ # # ][ # # ]
[ # # ][ # # ]
537 [ # # ]: 39 : if( MB_SUCCESS == result ) result = MB_FAILURE;
538 : : }
539 : : }
540 : :
541 : : // Release other resources
542 [ + - ]: 39 : if( MB_SUCCESS == result )
543 [ + - ]: 39 : result = write_finished();
544 : : else
545 [ # # ]: 0 : write_finished();
546 : :
547 : : // If write failed, remove file unless KEEP option was specified
548 [ - + ][ # # ]: 39 : if( MB_SUCCESS != result && created_file && MB_ENTITY_NOT_FOUND == opts.get_null_option( "KEEP" ) )
[ # # ][ # # ]
[ - + ]
549 : 0 : remove( filename );
550 : :
551 : 39 : return result;
552 : : }
553 : :
554 : 39 : ErrorCode WriteHDF5::write_file_impl( const char* filename, bool overwrite, const FileOptions& opts,
555 : : const EntityHandle* set_array, const int num_sets,
556 : : const std::vector< std::string >& qa_records, const Tag* tag_list, int num_tags,
557 : : int user_dimension )
558 : : {
559 : : ErrorCode result;
560 [ + - ]: 39 : std::list< TagDesc >::const_iterator t_itor;
561 [ + - ]: 39 : std::list< ExportSet >::iterator ex_itor;
562 : : EntityHandle elem_count, max_id;
563 : 39 : double times[NUM_TIMES] = { 0 };
564 : :
565 [ + - ][ - + ]: 39 : if( MB_SUCCESS != init() ) return error( MB_FAILURE );
566 : :
567 : : // See if we need to report times
568 : 39 : bool cputime = false;
569 [ + - ]: 39 : result = opts.get_null_option( "CPUTIME" );
570 [ - + ]: 39 : if( MB_SUCCESS == result ) cputime = true;
571 : :
572 [ + - ]: 39 : CpuTimer timer;
573 : :
574 [ + - ]: 39 : dbgOut.tprint( 1, "Gathering Mesh\n" );
575 [ + - ]: 39 : topState.start( "gathering mesh" );
576 : :
577 : : // Gather mesh to export
578 : 39 : exportList.clear();
579 [ + + ][ + - ]: 53 : if( 0 == num_sets || ( 1 == num_sets && set_array[0] == 0 ) )
[ - + ]
580 : : {
581 [ + - ]: 14 : result = gather_all_mesh();
582 [ + - ]: 14 : topState.end( result );
583 [ - + ][ # # ]: 14 : CHK_MB_ERR_0( result );
[ # # ][ # # ]
584 : : }
585 : : else
586 : : {
587 [ + - ]: 25 : std::vector< EntityHandle > passed_export_list( set_array, set_array + num_sets );
588 [ + - ]: 25 : result = gather_mesh_info( passed_export_list );
589 [ + - ]: 25 : topState.end( result );
590 [ - + ][ # # ]: 25 : CHK_MB_ERR_0( result );
[ # # ][ # # ]
[ + - ]
591 : : }
592 : :
593 [ + - ]: 39 : times[GATHER_TIME] = timer.time_elapsed();
594 : :
595 : : // if (nodeSet.range.size() == 0)
596 : : // return error(MB_ENTITY_NOT_FOUND);
597 : :
598 [ + - ]: 39 : dbgOut.tprint( 1, "Checking ID space\n" );
599 : :
600 : : // Make sure ID space is sufficient
601 [ + - ][ + - ]: 39 : elem_count = nodeSet.range.size() + setSet.range.size();
602 [ + - ][ + - ]: 91 : for( ex_itor = exportList.begin(); ex_itor != exportList.end(); ++ex_itor )
[ + + ]
603 [ + - ][ + - ]: 52 : elem_count += ex_itor->range.size();
604 : 39 : max_id = (EntityHandle)1 << ( 8 * sizeof( wid_t ) - 1 );
605 [ - + ]: 39 : if( elem_count > max_id )
606 : : {
607 [ # # ][ # # ]: 0 : MB_SET_ERR_CONT( "ID space insufficient for mesh size" );
[ # # ][ # # ]
[ # # ]
608 : 0 : return error( result );
609 : : }
610 : :
611 [ + - ]: 39 : dbgOut.tprint( 1, "Creating File\n" );
612 : :
613 : : // Figure out the dimension in which to write the mesh.
614 : : int mesh_dim;
615 [ + - ]: 39 : result = iFace->get_dimension( mesh_dim );
616 [ - + ][ # # ]: 39 : CHK_MB_ERR_0( result );
[ # # ][ # # ]
617 : :
618 [ - + ]: 39 : if( user_dimension < 1 ) user_dimension = mesh_dim;
619 [ - + ]: 39 : user_dimension = user_dimension > mesh_dim ? mesh_dim : user_dimension;
620 : :
621 : : // Create the file layout, including all tables (zero-ed) and
622 : : // all structure and meta information.
623 : 39 : const char* optnames[] = { "WRITE_PART", "FORMAT", 0 };
624 : : int junk;
625 [ + - ]: 39 : parallelWrite = ( MB_SUCCESS == opts.match_option( "PARALLEL", optnames, junk ) );
626 [ - + ]: 39 : if( parallelWrite )
627 : : {
628 : : // Just store Boolean value based on string option here.
629 : : // parallel_create_file will set writeProp accordingly.
630 : : // collectiveIO = (MB_SUCCESS == opts.get_null_option("COLLECTIVE"));
631 : : // dbgOut.printf(2, "'COLLECTIVE' option = %s\n", collectiveIO ? "YES" : "NO");
632 : : // Do this all the time, as it appears to be much faster than indep in some cases
633 : 0 : collectiveIO = true;
634 : : result =
635 [ # # ]: 0 : parallel_create_file( filename, overwrite, qa_records, opts, tag_list, num_tags, user_dimension, times );
636 : : }
637 : : else
638 : : {
639 [ + - ]: 39 : result = serial_create_file( filename, overwrite, qa_records, tag_list, num_tags, user_dimension );
640 : : }
641 [ - + ]: 39 : if( MB_SUCCESS != result ) return error( result );
642 : :
643 [ + - ]: 39 : times[CREATE_TIME] = timer.time_elapsed();
644 : :
645 [ + - ]: 39 : dbgOut.tprint( 1, "Writing Nodes.\n" );
646 : : // Write node coordinates
647 [ + - ][ + + ]: 39 : if( !nodeSet.range.empty() || parallelWrite )
[ - + ][ + + ]
648 : : {
649 [ + - ]: 38 : topState.start( "writing coords" );
650 [ + - ]: 38 : result = write_nodes();
651 [ + - ]: 38 : topState.end( result );
652 [ - + ]: 38 : if( MB_SUCCESS != result ) return error( result );
653 : : }
654 : :
655 [ + - ]: 39 : times[COORD_TIME] = timer.time_elapsed();
656 : :
657 [ + - ]: 39 : dbgOut.tprint( 1, "Writing connectivity.\n" );
658 : :
659 : : // Write element connectivity
660 [ + - ][ + - ]: 91 : for( ex_itor = exportList.begin(); ex_itor != exportList.end(); ++ex_itor )
[ + + ]
661 : : {
662 [ + - ][ + - ]: 52 : topState.start( "writing connectivity for ", ex_itor->name() );
[ + - ]
663 [ + - ][ + - ]: 52 : result = write_elems( *ex_itor );
664 [ + - ]: 52 : topState.end( result );
665 [ - + ]: 52 : if( MB_SUCCESS != result ) return error( result );
666 : : }
667 [ + - ]: 39 : times[CONN_TIME] = timer.time_elapsed();
668 : :
669 [ + - ]: 39 : dbgOut.tprint( 1, "Writing sets.\n" );
670 : :
671 : : // Write meshsets
672 [ + - ]: 39 : result = write_sets( times );
673 [ - + ]: 39 : if( MB_SUCCESS != result ) return error( result );
674 [ + - ]: 39 : debug_barrier();
675 : :
676 [ + - ]: 39 : times[SET_TIME] = timer.time_elapsed();
677 [ + - ]: 39 : dbgOut.tprint( 1, "Writing adjacencies.\n" );
678 : :
679 : : // Write adjacencies
680 : : // Tim says don't save node adjacencies!
681 : : #ifdef MB_H5M_WRITE_NODE_ADJACENCIES
682 : : result = write_adjacencies( nodeSet );
683 : : if( MB_SUCCESS != result ) return error( result );
684 : : #endif
685 [ + - ][ + - ]: 91 : for( ex_itor = exportList.begin(); ex_itor != exportList.end(); ++ex_itor )
[ + + ]
686 : : {
687 [ + - ][ + - ]: 52 : topState.start( "writing adjacencies for ", ex_itor->name() );
[ + - ]
688 [ + - ][ + - ]: 52 : result = write_adjacencies( *ex_itor );
689 [ + - ]: 52 : topState.end( result );
690 [ - + ]: 52 : if( MB_SUCCESS != result ) return error( result );
691 : : }
692 [ + - ]: 39 : times[ADJ_TIME] = timer.time_elapsed();
693 : :
694 [ + - ]: 39 : dbgOut.tprint( 1, "Writing tags.\n" );
695 : :
696 : : // Write tags
697 [ + - ][ + - ]: 386 : for( t_itor = tagList.begin(); t_itor != tagList.end(); ++t_itor )
[ + - ][ + - ]
[ + + ]
698 : : {
699 [ + - ]: 347 : std::string name;
700 [ + - ][ + - ]: 347 : iFace->tag_get_name( t_itor->tag_id, name );
701 [ + - ]: 347 : topState.start( "writing tag: ", name.c_str() );
702 [ + - ][ + - ]: 347 : result = write_tag( *t_itor, times );
703 [ + - ]: 347 : topState.end( result );
704 [ - + ][ + - ]: 347 : if( MB_SUCCESS != result ) return error( result );
705 : 347 : }
706 [ + - ]: 39 : times[TAG_TIME] = timer.time_elapsed();
707 : :
708 [ + - ]: 39 : times[TOTAL_TIME] = timer.time_since_birth();
709 : :
710 [ - + ][ # # ]: 39 : if( cputime ) { print_times( times ); }
711 : :
712 : 39 : return MB_SUCCESS;
713 : : }
714 : :
715 : 39 : ErrorCode WriteHDF5::initialize_mesh( const Range ranges[5] )
716 : : {
717 : : ErrorCode rval;
718 : :
719 [ + - ][ - + ]: 39 : if( !ranges[0].all_of_type( MBVERTEX ) ) return error( MB_FAILURE );
720 [ + - ]: 39 : nodeSet.range = ranges[0];
721 : 39 : nodeSet.type = MBVERTEX;
722 : 39 : nodeSet.num_nodes = 1;
723 : 39 : nodeSet.max_num_ents = nodeSet.max_num_adjs = 0;
724 : :
725 [ + - ][ - + ]: 39 : if( !ranges[4].all_of_type( MBENTITYSET ) ) return error( MB_FAILURE );
726 [ + - ]: 39 : setSet.range = ranges[4];
727 : 39 : setSet.type = MBENTITYSET;
728 : 39 : setSet.num_nodes = 0;
729 : 39 : setSet.max_num_ents = setSet.max_num_adjs = 0;
730 : 39 : maxNumSetContents = maxNumSetChildren = maxNumSetParents = 0;
731 : :
732 : 39 : exportList.clear();
733 [ + - ]: 39 : std::vector< Range > bins( 1024 ); // Sort entities by connectivity length
734 : : // Resize is expensive due to Range copy, so start big
735 [ + - ][ + + ]: 429 : for( EntityType type = MBEDGE; type < MBENTITYSET; ++type )
736 : : {
737 [ + - ]: 390 : ExportSet set;
738 : 390 : set.max_num_ents = set.max_num_adjs = 0;
739 [ + - ]: 390 : const int dim = CN::Dimension( type );
740 : :
741 : : // Group entities by connectivity length
742 : 390 : bins.clear();
743 [ + - ][ - + ]: 390 : assert( dim >= 0 && dim <= 4 );
744 [ + - ]: 390 : std::pair< Range::const_iterator, Range::const_iterator > p = ranges[dim].equal_range( type );
745 : 390 : Range::const_iterator i = p.first;
746 [ + - ][ + + ]: 442 : while( i != p.second )
747 : : {
748 : 52 : Range::const_iterator first = i;
749 : : EntityHandle const* conn;
750 : : int len, firstlen;
751 : :
752 : : // Dummy storage vector for structured mesh "get_connectivity" function
753 [ + - ]: 52 : std::vector< EntityHandle > storage;
754 : :
755 [ + - ][ + - ]: 52 : rval = iFace->get_connectivity( *i, conn, firstlen, false, &storage );
756 [ - + ]: 52 : if( MB_SUCCESS != rval ) return error( rval );
757 : :
758 [ + - ][ + - ]: 37056 : for( ++i; i != p.second; ++i )
[ + - ][ + + ]
759 : : {
760 [ + - ][ + - ]: 37006 : rval = iFace->get_connectivity( *i, conn, len, false, &storage );
761 [ - + ]: 37006 : if( MB_SUCCESS != rval ) return error( rval );
762 : :
763 [ + + ]: 37006 : if( len != firstlen ) break;
764 : : }
765 : :
766 [ + + ][ + - ]: 52 : if( firstlen >= (int)bins.size() ) bins.resize( firstlen + 1 );
767 [ + - ][ + - ]: 52 : bins[firstlen].merge( first, i );
[ + - ]
768 : 52 : }
769 : : // Create ExportSet for each group
770 [ + - ][ + - ]: 611 : for( std::vector< Range >::iterator j = bins.begin(); j != bins.end(); ++j )
[ + + ][ + - ]
771 : : {
772 [ + - ][ + - ]: 221 : if( j->empty() ) continue;
[ + + ]
773 : :
774 [ + - ]: 52 : set.range.clear();
775 : 52 : set.type = type;
776 [ + - ]: 52 : set.num_nodes = j - bins.begin();
777 [ + - ]: 52 : exportList.push_back( set );
778 [ + - ][ + - ]: 52 : exportList.back().range.swap( *j );
[ + - ]
779 : : }
780 : 390 : }
781 : :
782 : 39 : return MB_SUCCESS;
783 : : }
784 : :
785 : : // Gather the mesh to be written from a list of owning meshsets.
786 : 25 : ErrorCode WriteHDF5::gather_mesh_info( const std::vector< EntityHandle >& export_sets )
787 : : {
788 : : ErrorCode rval;
789 : :
790 : : int dim;
791 [ + - ]: 25 : Range range; // Temporary storage
792 [ + - ][ + + ]: 300 : Range ranges[5]; // Lists of entities to export, grouped by dimension
[ + + ]
[ # # # # ]
793 : :
794 : : // Gather list of all related sets
795 [ + - ]: 50 : std::vector< EntityHandle > stack( export_sets );
796 [ + - ]: 25 : std::copy( export_sets.begin(), export_sets.end(), stack.begin() );
797 [ + - ]: 50 : std::vector< EntityHandle > set_children;
798 [ + + ]: 198 : while( !stack.empty() )
799 : : {
800 [ + - ]: 173 : EntityHandle meshset = stack.back();
801 [ + - ]: 173 : stack.pop_back();
802 [ + - ]: 173 : ranges[4].insert( meshset );
803 : :
804 : : // Get contained sets
805 [ + - ]: 173 : range.clear();
806 [ + - ]: 173 : rval = iFace->get_entities_by_type( meshset, MBENTITYSET, range );
807 [ - + ][ # # ]: 173 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
808 [ + - ][ + - ]: 261 : for( Range::iterator ritor = range.begin(); ritor != range.end(); ++ritor )
[ + - ][ + - ]
[ + + ]
809 : : {
810 [ + - ][ + - ]: 88 : if( ranges[4].find( *ritor ) == ranges[4].end() ) stack.push_back( *ritor );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
811 : : }
812 : :
813 : : // Get child sets
814 : 173 : set_children.clear();
815 [ + - ]: 173 : rval = iFace->get_child_meshsets( meshset, set_children, 1 );
816 [ - + ][ # # ]: 173 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
817 [ + - ][ + - ]: 369 : for( std::vector< EntityHandle >::iterator vitor = set_children.begin(); vitor != set_children.end(); ++vitor )
[ + + ]
818 : : {
819 [ + - ][ + - ]: 196 : if( ranges[4].find( *vitor ) == ranges[4].end() ) stack.push_back( *vitor );
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ]
820 : : }
821 : : }
822 : :
823 : : // Gather list of all mesh entities from list of sets,
824 : : // grouped by dimension.
825 [ + - ][ + - ]: 138 : for( Range::iterator setitor = ranges[4].begin(); setitor != ranges[4].end(); ++setitor )
[ + - ][ + - ]
[ + + ]
826 : : {
827 [ + + ]: 565 : for( dim = 0; dim < 4; ++dim )
828 : : {
829 [ + - ]: 452 : range.clear();
830 [ + - ][ + - ]: 452 : rval = iFace->get_entities_by_dimension( *setitor, dim, range, false );
831 [ - + ][ # # ]: 452 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
832 : :
833 [ + - ]: 452 : ranges[dim].merge( range );
834 : : }
835 : : }
836 : :
837 : : // For each list of elements, append adjacent children and
838 : : // nodes to lists.
839 [ + + ]: 100 : for( dim = 3; dim > 0; --dim )
840 : : {
841 [ + + ]: 150 : for( int cdim = 1; cdim < dim; ++cdim )
842 : : {
843 [ + - ]: 75 : range.clear();
844 [ + - ]: 75 : rval = iFace->get_adjacencies( ranges[dim], cdim, false, range );
845 [ - + ][ # # ]: 75 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
846 [ + - ]: 75 : ranges[cdim].merge( range );
847 : : }
848 [ + - ]: 75 : range.clear();
849 [ + - ]: 75 : rval = writeUtil->gather_nodes_from_elements( ranges[dim], 0, range );
850 [ - + ][ # # ]: 75 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
851 [ + - ]: 75 : ranges[0].merge( range );
852 : : }
853 : :
854 [ + - ][ # # ]: 50 : return initialize_mesh( ranges );
855 : : }
856 : :
857 : : // Gather all the mesh and related information to be written.
858 : 14 : ErrorCode WriteHDF5::gather_all_mesh()
859 : : {
860 : : ErrorCode rval;
861 [ + - ][ + + ]: 154 : Range ranges[5];
[ # # ]
862 : :
863 [ + - ]: 14 : rval = iFace->get_entities_by_type( 0, MBVERTEX, ranges[0] );
864 [ - + ]: 14 : if( MB_SUCCESS != rval ) return error( rval );
865 : :
866 [ + - ]: 14 : rval = iFace->get_entities_by_dimension( 0, 1, ranges[1] );
867 [ - + ]: 14 : if( MB_SUCCESS != rval ) return error( rval );
868 : :
869 [ + - ]: 14 : rval = iFace->get_entities_by_dimension( 0, 2, ranges[2] );
870 [ - + ]: 14 : if( MB_SUCCESS != rval ) return error( rval );
871 : :
872 [ + - ]: 14 : rval = iFace->get_entities_by_dimension( 0, 3, ranges[3] );
873 [ - + ]: 14 : if( MB_SUCCESS != rval ) return error( rval );
874 : :
875 [ + - ]: 14 : rval = iFace->get_entities_by_type( 0, MBENTITYSET, ranges[4] );
876 [ - + ]: 14 : if( MB_SUCCESS != rval ) return error( rval );
877 : :
878 [ + - ][ + + ]: 84 : return initialize_mesh( ranges );
[ # # # # ]
879 : : }
880 : :
881 : 38 : ErrorCode WriteHDF5::write_nodes()
882 : : {
883 : : mhdf_Status status;
884 : : int dim, mesh_dim;
885 : : ErrorCode rval;
886 : : hid_t node_table;
887 : : long first_id, num_nodes;
888 : :
889 [ - + ]: 38 : if( !nodeSet.total_num_ents ) return MB_SUCCESS; // No nodes!
890 : :
891 [ + - ]: 38 : CHECK_OPEN_HANDLES;
892 : :
893 [ + - ]: 38 : rval = iFace->get_dimension( mesh_dim );
894 [ - + ][ # # ]: 38 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
895 : :
896 [ + - ]: 38 : debug_barrier();
897 [ + - ]: 38 : dbgOut.print( 3, "Opening Node Coords\n" );
898 [ + - ]: 38 : node_table = mhdf_openNodeCoords( filePtr, &num_nodes, &dim, &first_id, &status );
899 [ + - ][ - + ]: 38 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
900 [ + - ][ + - ]: 76 : IODebugTrack track( debugTrack, "nodes", num_nodes );
901 : :
902 : 38 : double* buffer = (double*)dataBuffer;
903 : : #ifdef BLOCKED_COORD_IO
904 : : int chunk_size = bufferSize / sizeof( double );
905 : : #else
906 : 38 : int chunk_size = bufferSize / ( 3 * sizeof( double ) );
907 : : #endif
908 : :
909 [ + - ]: 38 : long remaining = nodeSet.range.size();
910 : 38 : long num_writes = ( remaining + chunk_size - 1 ) / chunk_size;
911 [ - + ]: 38 : if( nodeSet.max_num_ents )
912 : : {
913 [ # # ]: 0 : assert( nodeSet.max_num_ents >= remaining );
914 : 0 : num_writes = ( nodeSet.max_num_ents + chunk_size - 1 ) / chunk_size;
915 : : }
916 : 38 : long remaining_writes = num_writes;
917 : :
918 : 38 : long offset = nodeSet.offset;
919 [ + - ]: 38 : Range::const_iterator iter = nodeSet.range.begin();
920 : 38 : dbgOut.printf( 3, "Writing %ld nodes in %ld blocks of %d\n", remaining, ( remaining + chunk_size - 1 ) / chunk_size,
921 [ + - ]: 38 : chunk_size );
922 [ + + ]: 76 : while( remaining )
923 : : {
924 : : (void)VALGRIND_MAKE_MEM_UNDEFINED( dataBuffer, bufferSize );
925 : 38 : long count = chunk_size < remaining ? chunk_size : remaining;
926 : 38 : remaining -= count;
927 : 38 : Range::const_iterator end = iter;
928 [ + - ]: 38 : end += count;
929 : :
930 : : #ifdef BLOCKED_COORD_IO
931 : : for( int d = 0; d < dim; d++ )
932 : : {
933 : : if( d < mesh_dim )
934 : : {
935 : : rval = writeUtil->get_node_coords( d, iter, end, count, buffer );
936 : : CHK_MB_ERR_1( rval, node_table, status );
937 : : }
938 : : else
939 : : memset( buffer, 0, count * sizeof( double ) );
940 : :
941 : : dbgOut.printf( 3, " writing %c node chunk %ld of %ld, %ld values at %ld\n", (char)( 'X' + d ),
942 : : num_writes - remaining_writes + 1, num_writes, count, offset );
943 : : mhdf_writeNodeCoordWithOpt( node_table, offset, count, d, buffer, writeProp, &status );
944 : : CHK_MHDF_ERR_1( status, node_table );
945 : : }
946 : : #else
947 [ + - ]: 38 : rval = writeUtil->get_node_coords( -1, iter, end, 3 * count, buffer );
948 [ - + ][ # # ]: 38 : CHK_MB_ERR_1( rval, node_table, status );
[ # # ][ # # ]
[ # # ]
949 : 38 : dbgOut.printf( 3, " writing node chunk %ld of %ld, %ld values at %ld\n", num_writes - remaining_writes + 1,
950 [ + - ]: 38 : num_writes, count, offset );
951 [ + - ]: 38 : mhdf_writeNodeCoordsWithOpt( node_table, offset, count, buffer, writeProp, &status );
952 [ + - ][ - + ]: 38 : CHK_MHDF_ERR_1( status, node_table );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
953 : : #endif
954 [ + - ]: 38 : track.record_io( offset, count );
955 : :
956 : 38 : iter = end;
957 : 38 : offset += count;
958 : 38 : --remaining_writes;
959 : : }
960 : :
961 : : // Do empty writes if necessary for parallel collective IO
962 [ - + ]: 38 : if( collectiveIO )
963 : : {
964 [ # # ]: 0 : while( remaining_writes-- )
965 : : {
966 [ # # ]: 0 : assert( writeProp != H5P_DEFAULT );
967 : : #ifdef BLOCKED_COORD_IO
968 : : for( int d = 0; d < dim; ++d )
969 : : {
970 : : dbgOut.printf( 3, " writing (empty) %c node chunk %ld of %ld.\n", (char)( 'X' + d ),
971 : : num_writes - remaining_writes, num_writes );
972 : : mhdf_writeNodeCoordWithOpt( node_table, offset, 0, d, 0, writeProp, &status );
973 : : CHK_MHDF_ERR_1( status, node_table );
974 : : }
975 : : #else
976 [ # # ]: 0 : dbgOut.printf( 3, " writing (empty) node chunk %ld of %ld.\n", num_writes - remaining_writes, num_writes );
977 [ # # ]: 0 : mhdf_writeNodeCoordsWithOpt( node_table, offset, 0, 0, writeProp, &status );
978 [ # # ][ # # ]: 0 : CHK_MHDF_ERR_1( status, node_table );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
979 : : #endif
980 : : }
981 : : }
982 : :
983 [ + - ]: 38 : mhdf_closeData( filePtr, node_table, &status );
984 [ + - ][ - + ]: 38 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
985 : :
986 [ + - ]: 38 : track.all_reduce();
987 : 38 : return MB_SUCCESS;
988 : : }
989 : :
990 : 52 : ErrorCode WriteHDF5::write_elems( ExportSet& elems )
991 : : {
992 : : mhdf_Status status;
993 : : ErrorCode rval;
994 : : long first_id;
995 : : int nodes_per_elem;
996 : : long table_size;
997 : :
998 [ + - ]: 52 : CHECK_OPEN_HANDLES;
999 : :
1000 [ + - ]: 52 : debug_barrier();
1001 : : dbgOut.printf( 2, "Writing %lu elements of type %s%d\n", (unsigned long)elems.range.size(),
1002 [ + - ][ + - ]: 52 : CN::EntityTypeName( elems.type ), elems.num_nodes );
[ + - ]
1003 [ + - ]: 52 : dbgOut.print( 3, "Writing elements", elems.range );
1004 : :
1005 [ + - ][ + - ]: 52 : hid_t elem_table = mhdf_openConnectivity( filePtr, elems.name(), &nodes_per_elem, &table_size, &first_id, &status );
1006 [ + - ][ - + ]: 52 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1007 [ + - ][ + - ]: 104 : IODebugTrack track( debugTrack, elems.name() && strlen( elems.name() ) ? elems.name() : "<ANONYMOUS ELEM SET?>",
[ + - ]
1008 [ + - ][ + - ]: 208 : table_size );
[ + - ][ + - ]
1009 : :
1010 [ - + ]: 52 : assert( (unsigned long)first_id <= elems.first_id );
1011 [ + - ][ - + ]: 52 : assert( (unsigned long)table_size >= elems.offset + elems.range.size() );
1012 : :
1013 : 52 : EntityHandle* buffer = (EntityHandle*)dataBuffer;
1014 : 52 : int chunk_size = bufferSize / ( elems.num_nodes * sizeof( wid_t ) );
1015 : 52 : long offset = elems.offset;
1016 [ + - ]: 52 : long remaining = elems.range.size();
1017 : 52 : long num_writes = ( remaining + chunk_size - 1 ) / chunk_size;
1018 [ - + ]: 52 : if( elems.max_num_ents )
1019 : : {
1020 [ # # ]: 0 : assert( elems.max_num_ents >= remaining );
1021 : 0 : num_writes = ( elems.max_num_ents + chunk_size - 1 ) / chunk_size;
1022 : : }
1023 : 52 : long remaining_writes = num_writes;
1024 [ + - ]: 52 : Range::iterator iter = elems.range.begin();
1025 : :
1026 [ + + ]: 104 : while( remaining )
1027 : : {
1028 : : (void)VALGRIND_MAKE_MEM_UNDEFINED( dataBuffer, bufferSize );
1029 : 52 : long count = chunk_size < remaining ? chunk_size : remaining;
1030 : 52 : remaining -= count;
1031 : :
1032 : 52 : Range::iterator next = iter;
1033 [ + - ]: 52 : next += count;
1034 [ + - ]: 52 : rval = writeUtil->get_element_connect( iter, next, elems.num_nodes, count * elems.num_nodes, buffer );
1035 [ - + ][ # # ]: 52 : CHK_MB_ERR_1( rval, elem_table, status );
[ # # ][ # # ]
[ # # ]
1036 : 52 : iter = next;
1037 : :
1038 [ + + ]: 103410 : for( long i = 0; i < count * nodes_per_elem; ++i )
1039 : : {
1040 [ + - ]: 103358 : buffer[i] = idMap.find( buffer[i] );
1041 [ - + ]: 103358 : if( 0 == buffer[i] )
1042 : : {
1043 [ # # ][ # # ]: 0 : MB_SET_ERR_CONT( "Invalid " << elems.name() << " element connectivity. Write Aborted" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1044 [ # # ]: 0 : mhdf_closeData( filePtr, elem_table, &status );
1045 : 0 : return error( MB_FAILURE );
1046 : : }
1047 : : }
1048 : :
1049 : : dbgOut.printf( 3, " writing node connectivity %ld of %ld, %ld values at %ld\n",
1050 [ + - ]: 52 : num_writes - remaining_writes + 1, num_writes, count, offset );
1051 [ + - ]: 52 : track.record_io( offset, count );
1052 [ + - ]: 52 : mhdf_writeConnectivityWithOpt( elem_table, offset, count, id_type, buffer, writeProp, &status );
1053 [ + - ][ - + ]: 52 : CHK_MHDF_ERR_1( status, elem_table );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1054 : :
1055 : 52 : offset += count;
1056 : 52 : --remaining_writes;
1057 : : }
1058 : :
1059 : : // Do empty writes if necessary for parallel collective IO
1060 [ - + ]: 52 : if( collectiveIO )
1061 : : {
1062 [ # # ]: 0 : while( remaining_writes-- )
1063 : : {
1064 [ # # ]: 0 : assert( writeProp != H5P_DEFAULT );
1065 : 0 : dbgOut.printf( 3, " writing (empty) connectivity chunk %ld of %ld.\n", num_writes - remaining_writes + 1,
1066 [ # # ]: 0 : num_writes );
1067 [ # # ]: 0 : mhdf_writeConnectivityWithOpt( elem_table, offset, 0, id_type, 0, writeProp, &status );
1068 [ # # ][ # # ]: 0 : CHK_MHDF_ERR_1( status, elem_table );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1069 : : }
1070 : : }
1071 : :
1072 [ + - ]: 52 : mhdf_closeData( filePtr, elem_table, &status );
1073 [ + - ][ - + ]: 52 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1074 : :
1075 [ + - ]: 52 : track.all_reduce();
1076 : 104 : return MB_SUCCESS;
1077 : : }
1078 : :
1079 : 966 : ErrorCode WriteHDF5::get_set_info( EntityHandle set, long& num_entities, long& num_children, long& num_parents,
1080 : : unsigned long& flags )
1081 : : {
1082 : : ErrorCode rval;
1083 : : int i;
1084 : : unsigned int u;
1085 : :
1086 [ + - ]: 966 : rval = iFace->get_number_entities_by_handle( set, i, false );
1087 [ - + ][ # # ]: 966 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
1088 : 966 : num_entities = i;
1089 : :
1090 [ + - ]: 966 : rval = iFace->num_child_meshsets( set, &i );
1091 [ - + ][ # # ]: 966 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
1092 : 966 : num_children = i;
1093 : :
1094 [ + - ]: 966 : rval = iFace->num_parent_meshsets( set, &i );
1095 [ - + ][ # # ]: 966 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
1096 : 966 : num_parents = i;
1097 : :
1098 [ + - ]: 966 : rval = iFace->get_meshset_options( set, u );
1099 [ - + ][ # # ]: 966 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
1100 : 966 : flags = u;
1101 : :
1102 : 966 : return MB_SUCCESS;
1103 : : }
1104 : :
1105 : 69 : ErrorCode WriteHDF5::write_set_data( const WriteUtilIface::EntityListType which_data, const hid_t handle,
1106 : : IODebugTrack& track, Range* ranged, Range* null_stripped,
1107 : : std::vector< long >* set_sizes )
1108 : : {
1109 : : // ranged must be non-null for CONTENTS and null for anything else
1110 [ - + ]: 69 : assert( ( which_data == WriteUtilIface::CONTENTS ) == ( 0 != ranged ) );
1111 : : ErrorCode rval;
1112 : : mhdf_Status status;
1113 : :
1114 [ + - ]: 69 : debug_barrier();
1115 : :
1116 : : // Function pointer type used to write set data
1117 : : void ( *write_func )( hid_t, long, long, hid_t, const void*, hid_t, mhdf_Status* );
1118 : : long max_vals; // Max over all procs of number of values to write to data set
1119 : : long offset; // Offset in HDF5 dataset at which to write next block of data
1120 [ + + + - ]: 69 : switch( which_data )
1121 : : {
1122 : : case WriteUtilIface::CONTENTS:
1123 [ + - ][ + - ]: 38 : assert( ranged != 0 && null_stripped != 0 && set_sizes != 0 );
[ - + ]
1124 : 38 : write_func = &mhdf_writeSetDataWithOpt;
1125 : 38 : max_vals = maxNumSetContents;
1126 : 38 : offset = setContentsOffset;
1127 [ + - ]: 38 : dbgOut.print( 2, "Writing set contents\n" );
1128 : 38 : break;
1129 : : case WriteUtilIface::CHILDREN:
1130 [ + - ][ + - ]: 16 : assert( !ranged && !null_stripped && !set_sizes );
[ - + ]
1131 : 16 : write_func = &mhdf_writeSetParentsChildrenWithOpt;
1132 : 16 : max_vals = maxNumSetChildren;
1133 : 16 : offset = setChildrenOffset;
1134 [ + - ]: 16 : dbgOut.print( 2, "Writing set child lists\n" );
1135 : 16 : break;
1136 : : case WriteUtilIface::PARENTS:
1137 [ + - ][ + - ]: 15 : assert( !ranged && !null_stripped && !set_sizes );
[ - + ]
1138 : 15 : write_func = &mhdf_writeSetParentsChildrenWithOpt;
1139 : 15 : max_vals = maxNumSetParents;
1140 : 15 : offset = setParentsOffset;
1141 [ + - ]: 15 : dbgOut.print( 2, "Writing set parent lists\n" );
1142 : 15 : break;
1143 : : default:
1144 : 0 : assert( false );
1145 : : return MB_FAILURE;
1146 : : }
1147 : : // assert(max_vals > 0); // Should have skipped this function otherwise
1148 : :
1149 : : // buffer to use for IO
1150 : 69 : wid_t* buffer = reinterpret_cast< wid_t* >( dataBuffer );
1151 : : // number of handles that will fit in the buffer
1152 : 69 : const size_t buffer_size = bufferSize / sizeof( EntityHandle );
1153 : : // the total number of write calls that must be made, including no-ops for collective io
1154 : 69 : const size_t num_total_writes = ( max_vals + buffer_size - 1 ) / buffer_size;
1155 : :
1156 : 69 : std::vector< SpecialSetData >::iterator si = specialSets.begin();
1157 : :
1158 [ + - ]: 69 : std::vector< wid_t > remaining; // data left over from prev iteration because it didn't fit in buffer
1159 : 69 : size_t remaining_offset = 0; // avoid erasing from front of 'remaining'
1160 : 69 : const EntityHandle* remaining_ptr = 0; // remaining for non-ranged data
1161 : 69 : size_t remaining_count = 0;
1162 : 69 : const wid_t* special_rem_ptr = 0;
1163 [ + - ][ + - ]: 69 : Range::const_iterator i = setSet.range.begin(), j, rhint, nshint;
[ + - ][ + - ]
1164 [ + + ][ + - ]: 69 : if( ranged ) rhint = ranged->begin();
1165 [ + + ][ + - ]: 69 : if( null_stripped ) nshint = null_stripped->begin();
1166 [ + + ]: 138 : for( size_t w = 0; w < num_total_writes; ++w )
1167 : : {
1168 [ + - ][ + - ]: 69 : if( i == setSet.range.end() && !remaining.empty() && !remaining_ptr )
[ - + ][ # # ]
[ # # ][ + - ]
[ - + # # ]
1169 : : {
1170 : : // If here, then we've written everything but we need to
1171 : : // make more write calls because we're doing collective IO
1172 : : // in parallel
1173 [ # # ]: 0 : ( *write_func )( handle, 0, 0, id_type, 0, writeProp, &status );
1174 [ # # ][ # # ]: 0 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1175 : 0 : continue;
1176 : : }
1177 : :
1178 : : // If we had some left-over data from a range-compacted set
1179 : : // from the last iteration, add it to the buffer now
1180 : 69 : size_t count = 0;
1181 [ - + ]: 69 : if( !remaining.empty() )
1182 : : {
1183 : 0 : count = remaining.size() - remaining_offset;
1184 [ # # ]: 0 : if( count > buffer_size )
1185 : : {
1186 [ # # ]: 0 : memcpy( buffer, &remaining[remaining_offset], buffer_size * sizeof( wid_t ) );
1187 : 0 : count = buffer_size;
1188 : 0 : remaining_offset += buffer_size;
1189 : : }
1190 : : else
1191 : : {
1192 [ # # ]: 0 : memcpy( buffer, &remaining[remaining_offset], count * sizeof( wid_t ) );
1193 : 0 : remaining_offset = 0;
1194 : 0 : remaining.clear();
1195 : : }
1196 : : }
1197 : : // If we had some left-over data from a non-range-compacted set
1198 : : // from the last iteration, add it to the buffer now
1199 [ - + ]: 69 : else if( remaining_ptr )
1200 : : {
1201 [ # # ]: 0 : if( remaining_count > buffer_size )
1202 : : {
1203 [ # # ]: 0 : rval = vector_to_id_list( remaining_ptr, buffer, buffer_size );
1204 [ # # ][ # # ]: 0 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
1205 : 0 : count = buffer_size;
1206 : 0 : remaining_ptr += count;
1207 : 0 : remaining_count -= count;
1208 : : }
1209 : : else
1210 : : {
1211 [ # # ]: 0 : rval = vector_to_id_list( remaining_ptr, buffer, remaining_count );
1212 [ # # ][ # # ]: 0 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
1213 : 0 : count = remaining_count;
1214 : 0 : remaining_ptr = 0;
1215 : 0 : remaining_count = 0;
1216 : : }
1217 : : }
1218 : : // If we had some left-over data from a "special" (i.e. parallel shared)
1219 : : // set.
1220 [ - + ]: 69 : else if( special_rem_ptr )
1221 : : {
1222 [ # # ]: 0 : if( remaining_count > buffer_size )
1223 : : {
1224 : 0 : memcpy( buffer, special_rem_ptr, buffer_size * sizeof( wid_t ) );
1225 : 0 : count = buffer_size;
1226 : 0 : special_rem_ptr += count;
1227 : 0 : remaining_count -= count;
1228 : : }
1229 : : else
1230 : : {
1231 : 0 : memcpy( buffer, special_rem_ptr, remaining_count * sizeof( wid_t ) );
1232 : 0 : count = remaining_count;
1233 : 0 : special_rem_ptr = 0;
1234 : 0 : remaining_count = 0;
1235 : : }
1236 : : }
1237 : :
1238 : : // While there is both space remaining in the buffer and
1239 : : // more sets to write, append more set data to buffer.
1240 : :
1241 [ + - ][ + - ]: 1166 : while( count < buffer_size && i != setSet.range.end() )
[ + - ][ + + ]
[ + - ]
[ + + # # ]
1242 : : {
1243 : : // Special case for "special" (i.e. parallel shared) sets:
1244 : : // we already have the data in a vector, just copy it.
1245 [ + - ][ - + ]: 1097 : if( si != specialSets.end() && si->setHandle == *i )
[ # # ][ # # ]
[ # # ][ + - ]
[ - + # # ]
1246 : : {
1247 : : std::vector< wid_t >& list =
1248 : : ( which_data == WriteUtilIface::CONTENTS )
1249 [ # # ]: 0 : ? si->contentIds
1250 [ # # ][ # # ]: 0 : : ( which_data == WriteUtilIface::PARENTS ) ? si->parentIds : si->childIds;
[ # # ][ # # ]
1251 : 0 : size_t append = list.size();
1252 [ # # ]: 0 : if( count + list.size() > buffer_size )
1253 : : {
1254 : 0 : append = buffer_size - count;
1255 [ # # ]: 0 : special_rem_ptr = &list[append];
1256 : 0 : remaining_count = list.size() - append;
1257 : : }
1258 [ # # ]: 0 : memcpy( buffer + count, &list[0], append * sizeof( wid_t ) );
1259 [ # # ]: 0 : ++i;
1260 [ # # ]: 0 : ++si;
1261 : 0 : count += append;
1262 : 0 : continue;
1263 : : }
1264 : :
1265 : 1097 : j = i;
1266 [ + - ]: 1097 : ++i;
1267 : : const EntityHandle* ptr;
1268 : : int len;
1269 : : unsigned char flags;
1270 [ + - ]: 1097 : rval = writeUtil->get_entity_list_pointers( j, i, &ptr, which_data, &len, &flags );
1271 [ - + ]: 1097 : if( MB_SUCCESS != rval ) return rval;
1272 [ + + ][ + + ]: 1097 : if( which_data == WriteUtilIface::CONTENTS && !( flags & MESHSET_ORDERED ) )
1273 : : {
1274 : : bool compacted;
1275 : 264 : remaining.clear();
1276 [ + + ]: 264 : if( len == 0 )
1277 : 46 : compacted = false;
1278 : : else
1279 : : {
1280 [ - + ]: 218 : assert( !( len % 2 ) );
1281 [ + - ]: 218 : rval = range_to_blocked_list( ptr, len / 2, remaining, compacted );
1282 [ - + ]: 218 : if( MB_SUCCESS != rval ) return rval;
1283 : : }
1284 [ + + ]: 264 : if( compacted )
1285 : : {
1286 [ + - ][ + - ]: 105 : rhint = ranged->insert( rhint, *j );
1287 [ + - ]: 105 : set_sizes->push_back( remaining.size() );
1288 : : }
1289 [ + + ]: 159 : else if( remaining.size() != (unsigned)len )
1290 : : {
1291 [ + - ][ + - ]: 113 : nshint = null_stripped->insert( nshint, *j );
1292 [ + - ]: 113 : set_sizes->push_back( remaining.size() );
1293 : : }
1294 : :
1295 [ + - ]: 264 : if( count + remaining.size() <= buffer_size )
1296 : : {
1297 [ + + ]: 264 : if( !remaining.empty() )
1298 [ + - ]: 215 : memcpy( buffer + count, &remaining[0], sizeof( wid_t ) * remaining.size() );
1299 : 264 : count += remaining.size();
1300 : 264 : remaining.clear();
1301 : 264 : remaining_offset = 0;
1302 : : }
1303 : : else
1304 : : {
1305 : 0 : remaining_offset = buffer_size - count;
1306 [ # # ]: 0 : memcpy( buffer + count, &remaining[0], sizeof( wid_t ) * remaining_offset );
1307 : 0 : count += remaining_offset;
1308 : 264 : }
1309 : : }
1310 : : else
1311 : : {
1312 [ - + ]: 833 : if( count + len > buffer_size )
1313 : : {
1314 : 0 : size_t append = buffer_size - count;
1315 : 0 : remaining_ptr = ptr + append;
1316 : 0 : remaining_count = len - append;
1317 : 0 : len = append;
1318 : : }
1319 : :
1320 [ + - ]: 833 : rval = vector_to_id_list( ptr, buffer + count, len );
1321 : 1097 : count += len;
1322 : : }
1323 : : }
1324 : :
1325 : : // Write the buffer.
1326 [ + - ]: 69 : ( *write_func )( handle, offset, count, id_type, buffer, writeProp, &status );
1327 [ + - ][ - + ]: 69 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1328 [ + - ]: 69 : track.record_io( offset, count );
1329 : 69 : offset += count;
1330 : : }
1331 : :
1332 : 69 : return MB_SUCCESS;
1333 : : }
1334 : :
1335 : 39 : ErrorCode WriteHDF5::write_sets( double* times )
1336 : : {
1337 : : mhdf_Status status;
1338 : : ErrorCode rval;
1339 : : long first_id, size;
1340 : : hid_t table;
1341 [ + - ]: 39 : CpuTimer timer;
1342 : :
1343 [ + - ]: 39 : CHECK_OPEN_HANDLES;
1344 : : /* If no sets, just return success */
1345 [ - + ]: 39 : if( !writeSets ) return MB_SUCCESS;
1346 : :
1347 [ + - ]: 39 : debug_barrier();
1348 [ + - ][ + - ]: 39 : dbgOut.printf( 2, "Writing %lu non-shared sets\n", (unsigned long)setSet.range.size() );
1349 [ + - ]: 39 : dbgOut.print( 3, "Non-shared sets", setSet.range );
1350 : :
1351 : : /* Write set parents */
1352 [ + + ]: 39 : if( writeSetParents )
1353 : : {
1354 [ + - ]: 15 : topState.start( "writing parent lists for local sets" );
1355 [ + - ]: 15 : table = mhdf_openSetParents( filePtr, &size, &status );
1356 [ + - ][ - + ]: 15 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1357 [ + - ][ + - ]: 15 : IODebugTrack track( debugTrack, "SetParents", size );
1358 : :
1359 [ + - ]: 15 : rval = write_set_data( WriteUtilIface::PARENTS, table, track );
1360 [ + - ]: 15 : topState.end( rval );
1361 [ - + ][ # # ]: 15 : CHK_MB_ERR_1( rval, table, status );
[ # # ][ # # ]
[ # # ]
1362 : :
1363 [ + - ]: 15 : mhdf_closeData( filePtr, table, &status );
1364 [ + - ][ - + ]: 15 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1365 : :
1366 [ + - ]: 15 : times[SET_PARENT] = timer.time_elapsed();
1367 [ + - ][ + - ]: 15 : track.all_reduce();
1368 : : }
1369 : :
1370 : : /* Write set children */
1371 [ + + ]: 39 : if( writeSetChildren )
1372 : : {
1373 [ + - ]: 16 : topState.start( "writing child lists for local sets" );
1374 [ + - ]: 16 : table = mhdf_openSetChildren( filePtr, &size, &status );
1375 [ + - ][ - + ]: 16 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1376 [ + - ][ + - ]: 16 : IODebugTrack track( debugTrack, "SetChildren", size );
1377 : :
1378 [ + - ]: 16 : rval = write_set_data( WriteUtilIface::CHILDREN, table, track );
1379 [ + - ]: 16 : topState.end( rval );
1380 [ - + ][ # # ]: 16 : CHK_MB_ERR_1( rval, table, status );
[ # # ][ # # ]
[ # # ]
1381 : :
1382 [ + - ]: 16 : mhdf_closeData( filePtr, table, &status );
1383 [ + - ][ - + ]: 16 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1384 : :
1385 [ + - ]: 16 : times[SET_CHILD] = timer.time_elapsed();
1386 [ + - ][ + - ]: 16 : track.all_reduce();
1387 : : }
1388 : :
1389 : : /* Write set contents */
1390 [ + - ][ + - ]: 78 : Range ranged_sets, null_stripped_sets;
1391 [ + - ]: 78 : std::vector< long > set_sizes;
1392 [ + + ]: 39 : if( writeSetContents )
1393 : : {
1394 [ + - ]: 38 : topState.start( "writing content lists for local sets" );
1395 [ + - ]: 38 : table = mhdf_openSetData( filePtr, &size, &status );
1396 [ + - ][ - + ]: 38 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1397 [ + - ][ + - ]: 38 : IODebugTrack track( debugTrack, "SetContents", size );
1398 : :
1399 [ + - ]: 38 : rval = write_set_data( WriteUtilIface::CONTENTS, table, track, &ranged_sets, &null_stripped_sets, &set_sizes );
1400 [ + - ]: 38 : topState.end( rval );
1401 [ - + ][ # # ]: 38 : CHK_MB_ERR_1( rval, table, status );
[ # # ][ # # ]
[ # # ]
1402 : :
1403 [ + - ]: 38 : mhdf_closeData( filePtr, table, &status );
1404 [ + - ][ - + ]: 38 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1405 : :
1406 [ + - ]: 38 : times[SET_CONTENT] = timer.time_elapsed();
1407 [ + - ][ + - ]: 38 : track.all_reduce();
1408 : : }
1409 [ + - ][ + - ]: 39 : assert( ranged_sets.size() + null_stripped_sets.size() == set_sizes.size() );
[ - + ]
1410 : :
1411 : : /* Write set description table */
1412 : :
1413 [ + - ]: 39 : debug_barrier();
1414 [ + - ]: 39 : topState.start( "writing descriptions of local sets" );
1415 [ + - ][ + - ]: 39 : dbgOut.printf( 2, "Writing %lu non-shared sets\n", (unsigned long)setSet.range.size() );
1416 [ + - ]: 39 : dbgOut.print( 3, "Non-shared sets", setSet.range );
1417 : :
1418 : : /* Open the table */
1419 [ + - ]: 39 : table = mhdf_openSetMeta( filePtr, &size, &first_id, &status );
1420 [ + - ][ - + ]: 39 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1421 [ + - ][ + - ]: 78 : IODebugTrack track_meta( debugTrack, "SetMeta", size );
1422 : :
1423 : : /* Some debug stuff */
1424 [ + - ]: 39 : debug_barrier();
1425 [ + - ][ + - ]: 39 : dbgOut.printf( 2, "Writing %lu non-shared sets\n", (unsigned long)setSet.range.size() );
1426 [ + - ]: 39 : dbgOut.print( 3, "Non-shared sets", setSet.range );
1427 : :
1428 : : /* Counts and buffers and such */
1429 : 39 : mhdf_index_t* const buffer = reinterpret_cast< mhdf_index_t* >( dataBuffer );
1430 : 39 : const size_t buffer_size = bufferSize / ( 4 * sizeof( mhdf_index_t ) );
1431 [ + - ]: 39 : const size_t num_local_writes = ( setSet.range.size() + buffer_size - 1 ) / buffer_size;
1432 : 39 : const size_t num_global_writes = ( setSet.max_num_ents + buffer_size - 1 ) / buffer_size;
1433 [ - + ]: 39 : assert( num_local_writes <= num_global_writes );
1434 [ - + ]: 39 : assert( num_global_writes > 0 );
1435 : :
1436 : : /* data about sets for which number of handles written is
1437 : : * not the same as the number of handles in the set
1438 : : * (range-compacted or null handles stripped out)
1439 : : */
1440 [ + - ]: 39 : Range::const_iterator i = setSet.range.begin();
1441 [ + - ]: 39 : Range::const_iterator r = ranged_sets.begin();
1442 [ + - ]: 39 : Range::const_iterator s = null_stripped_sets.begin();
1443 [ + - ]: 39 : std::vector< mhdf_index_t >::const_iterator n = set_sizes.begin();
1444 [ + - ][ + - ]: 39 : assert( ranged_sets.size() + null_stripped_sets.size() == set_sizes.size() );
[ - + ]
1445 : :
1446 : : /* We write the end index for each list, rather than the count */
1447 : 39 : mhdf_index_t prev_contents_end = setContentsOffset - 1;
1448 : 39 : mhdf_index_t prev_children_end = setChildrenOffset - 1;
1449 : 39 : mhdf_index_t prev_parents_end = setParentsOffset - 1;
1450 : :
1451 : : /* While there is more data to write */
1452 : 39 : size_t offset = setSet.offset;
1453 [ + - ]: 39 : std::vector< SpecialSetData >::const_iterator si = specialSets.begin();
1454 [ + + ]: 78 : for( size_t w = 0; w < num_local_writes; ++w )
1455 : : {
1456 : : // Get a buffer full of data
1457 : 39 : size_t count = 0;
1458 [ + - ][ + - ]: 522 : while( count < buffer_size && i != setSet.range.end() )
[ + - ][ + + ]
[ + - ]
[ + + # # ]
1459 : : {
1460 : : // Get set properties
1461 : : long num_ent, num_child, num_parent;
1462 : : unsigned long flags;
1463 [ + - ][ - + ]: 483 : if( si != specialSets.end() && si->setHandle == *i )
[ # # ][ # # ]
[ # # ][ + - ]
[ - + # # ]
1464 : : {
1465 [ # # ]: 0 : flags = si->setFlags;
1466 [ # # ]: 0 : num_ent = si->contentIds.size();
1467 [ # # ]: 0 : num_child = si->childIds.size();
1468 [ # # ]: 0 : num_parent = si->parentIds.size();
1469 [ # # ]: 0 : ++si;
1470 [ # # ][ # # ]: 0 : if( r != ranged_sets.end() && *i == *r )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
[ # # # # ]
1471 : : {
1472 [ # # ]: 0 : assert( flags & mhdf_SET_RANGE_BIT );
1473 [ # # ]: 0 : ++r;
1474 [ # # ]: 0 : ++n;
1475 : : }
1476 [ # # ][ # # ]: 0 : else if( s != null_stripped_sets.end() && *i == *s )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
[ # # # # ]
1477 : : {
1478 [ # # ]: 0 : ++s;
1479 [ # # ]: 0 : ++n;
1480 : : }
1481 : : }
1482 : : else
1483 : : {
1484 [ + - ][ - + ]: 483 : assert( si == specialSets.end() || si->setHandle > *i );
[ # # ][ # # ]
[ # # ][ + - ]
[ # # ]
1485 : :
1486 : : // Get set properties
1487 [ + - ][ + - ]: 483 : rval = get_set_info( *i, num_ent, num_child, num_parent, flags );
1488 [ - + ][ # # ]: 483 : CHK_MB_ERR_1( rval, table, status );
[ # # ][ # # ]
[ # # ]
1489 : :
1490 : : // Check if size is something other than num handles in set
1491 [ + - ][ + - ]: 483 : if( r != ranged_sets.end() && *i == *r )
[ + + ][ + - ]
[ + - ][ + + ]
[ + - ]
[ + + # # ]
1492 : : {
1493 [ + - ]: 105 : num_ent = *n;
1494 [ + - ]: 105 : ++r;
1495 [ + - ]: 105 : ++n;
1496 : 105 : flags |= mhdf_SET_RANGE_BIT;
1497 : : }
1498 [ + - ][ + - ]: 378 : else if( s != null_stripped_sets.end() && *i == *s )
[ + + ][ + - ]
[ + - ][ + + ]
[ + - ]
[ + + # # ]
1499 : : {
1500 [ + - ]: 113 : num_ent = *n;
1501 [ + - ]: 113 : ++s;
1502 [ + - ]: 113 : ++n;
1503 : : }
1504 : : }
1505 : :
1506 : : // Put data in buffer
1507 : 483 : mhdf_index_t* local = buffer + 4 * count;
1508 : 483 : prev_contents_end += num_ent;
1509 : 483 : prev_children_end += num_child;
1510 : 483 : prev_parents_end += num_parent;
1511 : 483 : local[0] = prev_contents_end;
1512 : 483 : local[1] = prev_children_end;
1513 : 483 : local[2] = prev_parents_end;
1514 : 483 : local[3] = flags;
1515 : :
1516 : : // Iterate
1517 : 483 : ++count;
1518 [ + - ]: 483 : ++i;
1519 : : }
1520 : :
1521 : : // Write the data
1522 [ + - ][ + - ]: 39 : mhdf_writeSetMetaWithOpt( table, offset, count, MHDF_INDEX_TYPE, buffer, writeProp, &status );
1523 [ + - ][ - + ]: 39 : CHK_MHDF_ERR_1( status, table );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1524 [ + - ]: 39 : track_meta.record_io( offset, count );
1525 : 39 : offset += count;
1526 : : }
1527 [ + - ][ + - ]: 39 : assert( r == ranged_sets.end() );
[ - + ]
1528 [ + - ][ + - ]: 39 : assert( s == null_stripped_sets.end() );
[ - + ]
1529 [ + - ][ - + ]: 39 : assert( n == set_sizes.end() );
1530 : :
1531 : : /* If doing parallel write with collective IO, do null write
1532 : : * calls because other procs aren't done yet and write calls
1533 : : * are collective */
1534 [ - + ]: 39 : for( size_t w = num_local_writes; w != num_global_writes; ++w )
1535 : : {
1536 [ # # ][ # # ]: 0 : mhdf_writeSetMetaWithOpt( table, 0, 0, MHDF_INDEX_TYPE, 0, writeProp, &status );
1537 [ # # ][ # # ]: 0 : CHK_MHDF_ERR_1( status, table );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1538 : : }
1539 : :
1540 [ + - ]: 39 : topState.end();
1541 [ + - ]: 39 : mhdf_closeData( filePtr, table, &status );
1542 [ + - ][ - + ]: 39 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1543 : :
1544 [ + - ]: 39 : times[SET_META] = timer.time_elapsed();
1545 [ + - ]: 39 : track_meta.all_reduce();
1546 : :
1547 : 39 : return MB_SUCCESS;
1548 : : }
1549 : :
1550 : : template < class HandleRangeIter >
1551 : 780 : inline size_t count_num_handles( HandleRangeIter iter, HandleRangeIter end )
1552 : : {
1553 : 780 : size_t result = 0;
1554 [ + + ][ + + ]: 7173 : for( ; iter != end; ++iter )
1555 : 3265 : result += iter->second - iter->first + 1;
1556 : :
1557 : 780 : return result;
1558 : : }
1559 : :
1560 : : template < class HandleRangeIter >
1561 : 344 : inline ErrorCode range_to_id_list_templ( HandleRangeIter begin, HandleRangeIter end,
1562 : : const RangeMap< EntityHandle, WriteHDF5::wid_t >& idMap,
1563 : : WriteHDF5::wid_t* array )
1564 : : {
1565 : 344 : ErrorCode rval = MB_SUCCESS;
1566 [ + - ][ + - ]: 344 : RangeMap< EntityHandle, WriteHDF5::wid_t >::iterator ri = idMap.begin();
1567 : 344 : WriteHDF5::wid_t* i = array;
1568 [ + + ][ + - ]: 793 : for( HandleRangeIter pi = begin; pi != end; ++pi )
[ + - ][ + + ]
1569 : : {
1570 [ + - ]: 293 : EntityHandle h = pi->first;
1571 [ + + ][ + - ]: 898 : while( h <= pi->second )
[ + + ]
1572 : : {
1573 [ + - ][ + - ]: 449 : ri = idMap.lower_bound( ri, idMap.end(), h );
[ + - ][ + - ]
1574 [ + - ][ + - ]: 449 : if( ri == idMap.end() || ri->begin > h )
[ + - ][ + - ]
[ - + ][ + - ]
[ - + # # ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ - + # # ]
1575 : : {
1576 : 0 : rval = MB_ENTITY_NOT_FOUND;
1577 : 0 : *i = 0;
1578 : 0 : ++i;
1579 : 0 : ++h;
1580 : 0 : continue;
1581 : : }
1582 : :
1583 : : // compute the last available value of the found target range (ri iterator)
1584 [ + - ][ + - ]: 449 : WriteHDF5::wid_t last_valid_input_value_in_current_map_range = ri->begin + ri->count - 1;
[ + - ][ + - ]
1585 : : // limit the number of steps we do on top of h so we do not overflow the output range
1586 : : // span
1587 [ + - ][ + - ]: 449 : WriteHDF5::wid_t step_until = std::min( last_valid_input_value_in_current_map_range, pi->second );
[ + - ]
1588 : 449 : WriteHDF5::wid_t n = step_until - h + 1;
1589 [ - + ][ - + ]: 449 : assert( n > 0 ); // We must at least step 1
1590 : :
1591 [ + - ][ + - ]: 449 : WriteHDF5::wid_t id = ri->value + ( h - ri->begin );
[ + - ][ + - ]
1592 [ + + ][ + + ]: 2916 : for( WriteHDF5::wid_t j = 0; j < n; ++i, ++j )
1593 : 2467 : *i = id + j;
1594 : 449 : h += n;
1595 : : }
1596 : : }
1597 : :
1598 [ + - ][ - + ]: 344 : assert( i == array + count_num_handles( begin, end ) );
[ + - ][ - + ]
1599 : 344 : return rval;
1600 : : }
1601 : :
1602 : : template < class HandleRangeIter >
1603 : 436 : inline ErrorCode range_to_blocked_list_templ( HandleRangeIter begin, HandleRangeIter end,
1604 : : const RangeMap< EntityHandle, WriteHDF5::wid_t >& idMap,
1605 : : std::vector< WriteHDF5::wid_t >& output_id_list, bool& ranged_list )
1606 : : {
1607 : 436 : output_id_list.clear();
1608 [ - + + - ]: 436 : if( begin == end )
[ - + ]
1609 : : {
1610 : 0 : ranged_list = false;
1611 : 0 : return MB_SUCCESS;
1612 : : }
1613 : :
1614 : : // First try ranged format, but give up if we reach the
1615 : : // non-range format size.
1616 [ + - ][ + - ]: 436 : RangeMap< EntityHandle, WriteHDF5::wid_t >::iterator ri = idMap.begin();
1617 : :
1618 [ + - ][ + - ]: 436 : const size_t num_handles = count_num_handles( begin, end );
1619 : : // If we end up with more than this many range blocks, then
1620 : : // we're better off just writing the set as a simple list
1621 : 436 : size_t pairs_remaining = num_handles / 2;
1622 [ + + ][ + - ]: 6154 : for( HandleRangeIter pi = begin; pi != end; ++pi )
[ + - ][ + + ]
1623 : : {
1624 [ + - ]: 2972 : EntityHandle h = pi->first;
1625 : 5944 : WriteHDF5::wid_t local_mapped_from_subrange = 0;
1626 [ + + ][ + - ]: 11716 : while( h <= pi->second )
[ + + ]
1627 : : {
1628 [ + - ][ + - ]: 5998 : ri = idMap.lower_bound( ri, idMap.end(), h );
[ + - ][ + - ]
1629 [ + - ][ + - ]: 5998 : if( ri == idMap.end() || ri->begin > h )
[ + - ][ + - ]
[ + + ][ + - ]
[ + + # # ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + + # # ]
1630 : : {
1631 : 60 : ++h;
1632 : 60 : continue;
1633 : : }
1634 : :
1635 [ + - ][ + - ]: 2969 : WriteHDF5::wid_t n = pi->second - pi->first + 1 - local_mapped_from_subrange;
1636 [ + - ][ - + ]: 5938 : if( n > ri->count ) n = ri->count;
[ # # ][ + - ]
[ - + ][ # # ]
1637 : :
1638 [ + - ][ + - ]: 5938 : WriteHDF5::wid_t id = ri->value + ( h - ri->begin );
[ + - ][ + - ]
1639 : : // see if we can go to the end of the range
1640 [ + - ][ + - ]: 5938 : if( id + n > ri->value + ri->count ) // we have to reduce n, because we cannot go over next subrange
[ - + ][ + - ]
[ + - ][ - + ]
1641 : : {
1642 [ # # ][ # # ]: 0 : if( ri->value + ri->count - id > 0 ) n = ri->value + ri->count - id;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1643 : : }
1644 : :
1645 : : // See if we can append it to the previous range
1646 [ + + ][ + - ]: 5938 : if( !output_id_list.empty() && output_id_list[output_id_list.size() - 2] + output_id_list.back() == id )
[ + - ][ + + ]
[ + + ][ + + ]
[ + - ][ + - ]
[ + + ][ + + ]
1647 [ + - ][ + - ]: 3100 : { output_id_list.back() += n; }
1648 : :
1649 : : // If we ran out of space, (or set is empty) just do list format
1650 [ + + ][ + + ]: 2838 : else if( !pairs_remaining )
1651 : : {
1652 : 226 : ranged_list = false;
1653 [ + - ][ + - ]: 226 : output_id_list.resize( num_handles );
1654 [ + - ][ + - ]: 226 : range_to_id_list_templ( begin, end, idMap, &output_id_list[0] );
[ + - ][ + - ]
1655 [ + - ][ + - ]: 226 : output_id_list.erase( std::remove( output_id_list.begin(), output_id_list.end(), 0u ),
1656 [ + - ][ + - ]: 226 : output_id_list.end() );
1657 : 226 : return MB_SUCCESS;
1658 : : }
1659 : :
1660 : : //
1661 : : else
1662 : : {
1663 : 2612 : --pairs_remaining;
1664 [ + - ][ + - ]: 2612 : output_id_list.push_back( id );
1665 [ + - ][ + - ]: 2612 : output_id_list.push_back( n );
1666 : : }
1667 : 5712 : local_mapped_from_subrange += n; // we already mapped so many
1668 : 5712 : h += n;
1669 : : }
1670 : : }
1671 : :
1672 : 210 : ranged_list = true;
1673 : 436 : return MB_SUCCESS;
1674 : : }
1675 : :
1676 : 218 : ErrorCode WriteHDF5::range_to_blocked_list( const Range& input_range, std::vector< wid_t >& output_id_list,
1677 : : bool& ranged_list )
1678 : : {
1679 : : return range_to_blocked_list_templ( input_range.const_pair_begin(), input_range.const_pair_end(), idMap,
1680 : 218 : output_id_list, ranged_list );
1681 : : }
1682 : :
1683 : 218 : ErrorCode WriteHDF5::range_to_blocked_list( const EntityHandle* array, size_t num_input_ranges,
1684 : : std::vector< wid_t >& output_id_list, bool& ranged_list )
1685 : : {
1686 : : // We assume this in the cast on the following line
1687 : : typedef std::pair< EntityHandle, EntityHandle > mtype;
1688 [ - + ]: 218 : assert( sizeof( mtype ) == 2 * sizeof( EntityHandle ) );
1689 : 218 : const mtype* arr = reinterpret_cast< const mtype* >( array );
1690 : 218 : return range_to_blocked_list_templ( arr, arr + num_input_ranges, idMap, output_id_list, ranged_list );
1691 : : }
1692 : :
1693 : 118 : ErrorCode WriteHDF5::range_to_id_list( const Range& range, wid_t* array )
1694 : : {
1695 : 118 : return range_to_id_list_templ( range.const_pair_begin(), range.const_pair_end(), idMap, array );
1696 : : }
1697 : :
1698 : 833 : ErrorCode WriteHDF5::vector_to_id_list( const EntityHandle* input, size_t input_len, wid_t* output, size_t& output_len,
1699 : : bool remove_zeros )
1700 : : {
1701 : 833 : const EntityHandle* i_iter = input;
1702 : 833 : const EntityHandle* i_end = input + input_len;
1703 : 833 : wid_t* o_iter = output;
1704 [ + + ]: 4331 : for( ; i_iter != i_end; ++i_iter )
1705 : : {
1706 : 3498 : wid_t id = idMap.find( *i_iter );
1707 [ - + ][ # # ]: 3498 : if( !remove_zeros || id != 0 )
1708 : : {
1709 : 3498 : *o_iter = id;
1710 : 3498 : ++o_iter;
1711 : : }
1712 : : }
1713 : 833 : output_len = o_iter - output;
1714 : :
1715 : 833 : return MB_SUCCESS;
1716 : : }
1717 : :
1718 : 0 : ErrorCode WriteHDF5::vector_to_id_list( const std::vector< EntityHandle >& input, std::vector< wid_t >& output,
1719 : : bool remove_zeros )
1720 : : {
1721 [ # # ]: 0 : output.resize( input.size() );
1722 : 0 : size_t output_size = 0;
1723 [ # # ][ # # ]: 0 : ErrorCode rval = vector_to_id_list( &input[0], input.size(), &output[0], output_size, remove_zeros );
[ # # ]
1724 [ # # ]: 0 : output.resize( output_size );
1725 : 0 : return rval;
1726 : : }
1727 : :
1728 : 833 : ErrorCode WriteHDF5::vector_to_id_list( const EntityHandle* input, wid_t* output, size_t count )
1729 : : {
1730 : : size_t output_len;
1731 [ + - ]: 833 : return vector_to_id_list( input, count, output, output_len, false );
1732 : : }
1733 : :
1734 : 37080 : inline ErrorCode WriteHDF5::get_adjacencies( EntityHandle entity, std::vector< wid_t >& adj )
1735 : : {
1736 : : const EntityHandle* adj_array;
1737 : : int num_adj;
1738 [ + - ]: 37080 : ErrorCode rval = writeUtil->get_adjacencies( entity, adj_array, num_adj );
1739 [ - + ]: 37080 : if( MB_SUCCESS != rval ) return error( rval );
1740 : :
1741 : 37080 : size_t j = 0;
1742 [ + - ]: 37080 : adj.resize( num_adj );
1743 [ + + ]: 37128 : for( int i = 0; i < num_adj; ++i )
1744 [ + - ][ + - ]: 48 : if( wid_t id = idMap.find( adj_array[i] ) ) adj[j++] = id;
[ + - ]
1745 [ + - ]: 37080 : adj.resize( j );
1746 : :
1747 : 37080 : return MB_SUCCESS;
1748 : : }
1749 : :
1750 : 52 : ErrorCode WriteHDF5::write_adjacencies( const ExportSet& elements )
1751 : : {
1752 : : ErrorCode rval;
1753 : : mhdf_Status status;
1754 [ + - ]: 52 : Range::const_iterator iter;
1755 [ + - ]: 52 : const Range::const_iterator end = elements.range.end();
1756 [ + - ]: 52 : std::vector< wid_t > adj_list;
1757 : :
1758 [ + - ]: 104 : CHECK_OPEN_HANDLES;
1759 : :
1760 [ + - ]: 52 : debug_barrier();
1761 : :
1762 : : /* Count Adjacencies */
1763 : 52 : long count = 0;
1764 : : // for (iter = elements.range.begin(); iter != end; ++iter) {
1765 : : // adj_list.clear();
1766 : : // rval = get_adjacencies(*iter, adj_list);CHK_MB_ERR_0(rval);
1767 : : //
1768 : : // if (adj_list.size() > 0)
1769 : : // count += adj_list.size() + 2;
1770 : : //}
1771 : :
1772 : : // if (count == 0)
1773 : : // return MB_SUCCESS;
1774 : :
1775 : 52 : long offset = elements.adj_offset;
1776 [ + + ]: 52 : if( elements.max_num_adjs == 0 ) return MB_SUCCESS;
1777 : :
1778 : : /* Create data list */
1779 [ + - ][ + - ]: 2 : hid_t table = mhdf_openAdjacency( filePtr, elements.name(), &count, &status );
1780 [ + - ][ - + ]: 2 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1781 [ + - ][ + - ]: 4 : IODebugTrack track( debugTrack, "Adjacencies", count );
1782 : :
1783 : : /* Write data */
1784 : 2 : wid_t* buffer = (wid_t*)dataBuffer;
1785 : 2 : long chunk_size = bufferSize / sizeof( wid_t );
1786 : 2 : long num_writes = ( elements.max_num_adjs + chunk_size - 1 ) / chunk_size;
1787 : : (void)VALGRIND_MAKE_MEM_UNDEFINED( dataBuffer, bufferSize );
1788 : 2 : count = 0;
1789 [ + - ][ + - ]: 26 : for( iter = elements.range.begin(); iter != end; ++iter )
[ + - ][ + + ]
1790 : : {
1791 : 24 : adj_list.clear();
1792 [ + - ][ + - ]: 24 : rval = get_adjacencies( *iter, adj_list );
1793 [ - + ][ # # ]: 24 : CHK_MB_ERR_1( rval, table, status );
[ # # ][ # # ]
[ # # ]
1794 [ - + ]: 24 : if( adj_list.size() == 0 ) continue;
1795 : :
1796 : : // If buffer is full, flush it
1797 [ - + ]: 24 : if( count + adj_list.size() + 2 > (unsigned long)chunk_size )
1798 : : {
1799 [ # # ]: 0 : dbgOut.print( 3, " writing adjacency chunk.\n" );
1800 [ # # ]: 0 : track.record_io( offset, count );
1801 [ # # ]: 0 : mhdf_writeAdjacencyWithOpt( table, offset, count, id_type, buffer, writeProp, &status );
1802 [ # # ][ # # ]: 0 : CHK_MHDF_ERR_1( status, table );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1803 : : (void)VALGRIND_MAKE_MEM_UNDEFINED( dataBuffer, bufferSize );
1804 : :
1805 : 0 : offset += count;
1806 : 0 : count = 0;
1807 : : }
1808 : :
1809 [ + - ][ + - ]: 24 : buffer[count++] = idMap.find( *iter );
1810 : 24 : buffer[count++] = adj_list.size();
1811 : :
1812 [ - + ]: 24 : assert( adj_list.size() + 2 < (unsigned long)chunk_size );
1813 [ + - ]: 24 : memcpy( buffer + count, &adj_list[0], adj_list.size() * sizeof( wid_t ) );
1814 : 24 : count += adj_list.size();
1815 : : }
1816 : :
1817 [ + - ]: 2 : if( count )
1818 : : {
1819 [ + - ]: 2 : dbgOut.print( 2, " writing final adjacency chunk.\n" );
1820 [ + - ]: 2 : mhdf_writeAdjacencyWithOpt( table, offset, count, id_type, buffer, writeProp, &status );
1821 [ + - ][ - + ]: 2 : CHK_MHDF_ERR_1( status, table );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1822 : :
1823 : 2 : offset += count;
1824 : 2 : count = 0;
1825 : 2 : --num_writes;
1826 : : }
1827 : :
1828 : : // Do empty writes if necessary for parallel collective IO
1829 [ - + ]: 2 : if( collectiveIO )
1830 : : {
1831 [ # # ]: 0 : while( num_writes > 0 )
1832 : : {
1833 : 0 : --num_writes;
1834 [ # # ]: 0 : assert( writeProp != H5P_DEFAULT );
1835 [ # # ]: 0 : dbgOut.print( 2, " writing empty adjacency chunk.\n" );
1836 [ # # ]: 0 : mhdf_writeAdjacencyWithOpt( table, offset, 0, id_type, 0, writeProp, &status );
1837 [ # # ][ # # ]: 0 : CHK_MHDF_ERR_1( status, table );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1838 : : }
1839 : : }
1840 : :
1841 [ + - ]: 2 : mhdf_closeData( filePtr, table, &status );
1842 [ + - ][ - + ]: 2 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1843 : :
1844 [ + - ]: 2 : track.all_reduce();
1845 : 52 : return MB_SUCCESS;
1846 : : }
1847 : :
1848 : 347 : ErrorCode WriteHDF5::write_tag( const TagDesc& tag_data, double* times )
1849 : : {
1850 [ + - ]: 347 : std::string name;
1851 [ + - ]: 347 : ErrorCode rval = iFace->tag_get_name( tag_data.tag_id, name );
1852 [ - + ]: 347 : if( MB_SUCCESS != rval ) return error( rval );
1853 : :
1854 [ + - ]: 694 : CHECK_OPEN_HANDLES;
1855 [ + - ]: 347 : debug_barrier();
1856 [ + - ]: 347 : dbgOut.tprintf( 1, "Writing tag: \"%s\"\n", name.c_str() );
1857 : :
1858 : : int moab_size, elem_size, array_len;
1859 : : DataType moab_type;
1860 : : mhdf_TagDataType mhdf_type;
1861 : : hid_t hdf5_type;
1862 [ + - ]: 347 : rval = get_tag_size( tag_data.tag_id, moab_type, moab_size, elem_size, array_len, mhdf_type, hdf5_type );
1863 [ - + ]: 347 : if( MB_SUCCESS != rval ) return error( rval );
1864 : :
1865 [ + - ]: 347 : CpuTimer timer;
1866 [ + + ][ + + ]: 347 : if( array_len == MB_VARIABLE_LENGTH && tag_data.write_sparse )
1867 : : {
1868 [ + - ]: 23 : dbgOut.printf( 2, "Writing sparse data for var-len tag: \"%s\"\n", name.c_str() );
1869 [ + - ]: 23 : rval = write_var_len_tag( tag_data, name, moab_type, hdf5_type, elem_size );
1870 [ + - ]: 23 : times[VARLEN_TAG_TIME] += timer.time_elapsed();
1871 : : }
1872 : : else
1873 : : {
1874 : 324 : int data_len = elem_size;
1875 [ + - ]: 324 : if( moab_type != MB_TYPE_BIT ) data_len *= array_len;
1876 [ + + ]: 324 : if( tag_data.write_sparse )
1877 : : {
1878 [ + - ]: 95 : dbgOut.printf( 2, "Writing sparse data for tag: \"%s\"\n", name.c_str() );
1879 [ + - ]: 95 : rval = write_sparse_tag( tag_data, name, moab_type, hdf5_type, data_len );
1880 [ + - ]: 95 : times[SPARSE_TAG_TIME] += timer.time_elapsed();
1881 : : }
1882 [ + - ][ + + ]: 430 : for( size_t i = 0; MB_SUCCESS == rval && i < tag_data.dense_list.size(); ++i )
[ + + ]
1883 : : {
1884 [ + - ][ + - ]: 106 : const ExportSet* set = find( tag_data.dense_list[i] );
1885 [ - + ]: 106 : assert( 0 != set );
1886 [ + - ]: 106 : debug_barrier();
1887 [ + - ][ + - ]: 106 : dbgOut.printf( 2, "Writing dense data for tag: \"%s\" on group \"%s\"\n", name.c_str(), set->name() );
1888 [ + - ][ + - ]: 106 : subState.start( "writing dense data for tag: ", ( name + ":" + set->name() ).c_str() );
[ + - ][ + - ]
1889 [ + - ]: 106 : rval = write_dense_tag( tag_data, *set, name, moab_type, hdf5_type, data_len );
1890 [ + - ]: 106 : subState.end( rval );
1891 : : }
1892 [ + - ]: 324 : times[DENSE_TAG_TIME] += timer.time_elapsed();
1893 : : }
1894 : :
1895 [ + - ]: 347 : H5Tclose( hdf5_type );
1896 [ - + ]: 694 : return MB_SUCCESS == rval ? MB_SUCCESS : error( rval );
1897 : : }
1898 : :
1899 : 118 : ErrorCode WriteHDF5::write_sparse_ids( const TagDesc& tag_data, const Range& range, hid_t id_table, size_t table_size,
1900 : : const char* name )
1901 : : {
1902 : : ErrorCode rval;
1903 : : mhdf_Status status;
1904 : :
1905 [ + - ]: 118 : CHECK_OPEN_HANDLES;
1906 : :
1907 [ + - ][ + - ]: 236 : std::string tname( name ? name : "<UNKNOWN TAG?>" );
1908 [ + - ]: 118 : tname += " - Ids";
1909 [ + - ]: 236 : IODebugTrack track( debugTrack, tname, table_size );
1910 : :
1911 : : // Set up data buffer for writing IDs
1912 : 118 : size_t chunk_size = bufferSize / sizeof( wid_t );
1913 : 118 : wid_t* id_buffer = (wid_t*)dataBuffer;
1914 : :
1915 : : // Write IDs of tagged entities.
1916 [ + - ]: 118 : long remaining = range.size();
1917 : 118 : long offset = tag_data.sparse_offset;
1918 : 118 : long num_writes = ( remaining + chunk_size - 1 ) / chunk_size;
1919 [ - + ]: 118 : if( tag_data.max_num_ents )
1920 : : {
1921 [ # # ]: 0 : assert( tag_data.max_num_ents >= (unsigned long)remaining );
1922 : 0 : num_writes = ( tag_data.max_num_ents + chunk_size - 1 ) / chunk_size;
1923 : : }
1924 [ + - ]: 118 : Range::const_iterator iter = range.begin();
1925 [ + + ]: 236 : while( remaining )
1926 : : {
1927 : : (void)VALGRIND_MAKE_MEM_UNDEFINED( dataBuffer, bufferSize );
1928 : :
1929 : : // Write "chunk_size" blocks of data
1930 [ - + ]: 118 : long count = (unsigned long)remaining > chunk_size ? chunk_size : remaining;
1931 : 118 : remaining -= count;
1932 : 118 : Range::const_iterator stop = iter;
1933 [ + - ]: 118 : stop += count;
1934 [ + - ]: 118 : Range tmp;
1935 : : ;
1936 [ + - ]: 118 : tmp.merge( iter, stop );
1937 : 118 : iter = stop;
1938 [ + - ][ - + ]: 118 : assert( tmp.size() == (unsigned)count );
1939 : :
1940 [ + - ]: 118 : rval = range_to_id_list( tmp, id_buffer );
1941 [ - + ][ # # ]: 118 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
1942 : :
1943 : : // Write the data
1944 [ + - ]: 118 : dbgOut.print( 3, " writing sparse tag entity chunk.\n" );
1945 [ + - ]: 118 : track.record_io( offset, count );
1946 [ + - ]: 118 : mhdf_writeSparseTagEntitiesWithOpt( id_table, offset, count, id_type, id_buffer, writeProp, &status );
1947 [ + - ][ - + ]: 118 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1948 : :
1949 : 118 : offset += count;
1950 [ + - ]: 118 : --num_writes;
1951 : 118 : } // while (remaining)
1952 : :
1953 : : // Do empty writes if necessary for parallel collective IO
1954 [ - + ]: 118 : if( collectiveIO )
1955 : : {
1956 [ # # ]: 0 : while( num_writes-- )
1957 : : {
1958 [ # # ]: 0 : assert( writeProp != H5P_DEFAULT );
1959 [ # # ]: 0 : dbgOut.print( 3, " writing empty sparse tag entity chunk.\n" );
1960 [ # # ]: 0 : mhdf_writeSparseTagEntitiesWithOpt( id_table, offset, 0, id_type, 0, writeProp, &status );
1961 [ # # ][ # # ]: 0 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1962 : : }
1963 : : }
1964 : :
1965 [ + - ]: 118 : track.all_reduce();
1966 : 236 : return MB_SUCCESS;
1967 : : }
1968 : :
1969 : 95 : ErrorCode WriteHDF5::write_sparse_tag( const TagDesc& tag_data, const std::string& name, DataType mb_data_type,
1970 : : hid_t value_type, int value_type_size )
1971 : : {
1972 : : ErrorCode rval;
1973 : : mhdf_Status status;
1974 : : hid_t tables[3];
1975 : : long table_size, data_size;
1976 : :
1977 [ + - ]: 95 : CHECK_OPEN_HANDLES;
1978 : :
1979 : : // Get entities for which to write tag values
1980 [ + - ]: 190 : Range range;
1981 [ + - ]: 95 : rval = get_sparse_tagged_entities( tag_data, range );
1982 : :
1983 : : // Open tables to write info
1984 [ + - ]: 95 : mhdf_openSparseTagData( filePtr, name.c_str(), &table_size, &data_size, tables, &status );
1985 [ + - ][ - + ]: 95 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1986 [ + - ][ - + ]: 95 : assert( range.size() + tag_data.sparse_offset <= (unsigned long)table_size );
1987 : : // Fixed-length tag
1988 [ - + ]: 95 : assert( table_size == data_size );
1989 : :
1990 : : // Write IDs for tagged entities
1991 [ + - ]: 95 : subState.start( "writing sparse ids for tag: ", name.c_str() );
1992 [ + - ]: 95 : rval = write_sparse_ids( tag_data, range, tables[0], table_size, name.c_str() );
1993 [ + - ]: 95 : subState.end( rval );
1994 [ - + ][ # # ]: 95 : CHK_MB_ERR_2( rval, tables, status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1995 [ + - ]: 95 : mhdf_closeData( filePtr, tables[0], &status );
1996 [ + - ][ - + ]: 95 : CHK_MHDF_ERR_1( status, tables[1] );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1997 : :
1998 : : // Set up data buffer for writing tag values
1999 [ + - ][ + - ]: 190 : IODebugTrack track( debugTrack, name + " Data", data_size );
2000 [ + - ]: 95 : subState.start( "writing sparse values for tag: ", name.c_str() );
2001 : : rval = write_tag_values( tag_data.tag_id, tables[1], tag_data.sparse_offset, range, mb_data_type, value_type,
2002 [ + - ]: 95 : value_type_size, tag_data.max_num_ents, track );
2003 [ + - ]: 95 : subState.end( rval );
2004 [ - + ][ # # ]: 95 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2005 [ + - ]: 95 : mhdf_closeData( filePtr, tables[1], &status );
2006 [ + - ][ - + ]: 95 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2007 : :
2008 [ + - ]: 95 : track.all_reduce();
2009 : 190 : return MB_SUCCESS;
2010 : : }
2011 : :
2012 : 23 : ErrorCode WriteHDF5::write_var_len_indices( const TagDesc& tag_data, const Range& range, hid_t idx_table,
2013 : : size_t table_size, int /*type_size*/, const char* name )
2014 : : {
2015 : : ErrorCode rval;
2016 : : mhdf_Status status;
2017 : :
2018 [ + - ]: 23 : CHECK_OPEN_HANDLES;
2019 : :
2020 [ + - ][ + - ]: 46 : std::string tname( name ? name : "<UNKNOWN TAG?>" );
2021 [ + - ]: 23 : tname += " - End Indices";
2022 [ + - ]: 46 : IODebugTrack track( debugTrack, tname, table_size );
2023 : :
2024 : : // Set up data buffer for writing indices
2025 [ + - ]: 23 : size_t chunk_size = bufferSize / ( std::max( sizeof( void* ), sizeof( long ) ) + sizeof( int ) );
2026 : 23 : mhdf_index_t* idx_buffer = (mhdf_index_t*)dataBuffer;
2027 : 23 : const void** junk = (const void**)dataBuffer;
2028 [ + - ]: 23 : int* size_buffer = (int*)( dataBuffer + chunk_size * std::max( sizeof( void* ), sizeof( mhdf_index_t ) ) );
2029 : :
2030 : : // Write IDs of tagged entities.
2031 : 23 : long data_offset = tag_data.var_data_offset - 1; // Offset at which to write data buffer
2032 [ + - ]: 23 : size_t remaining = range.size();
2033 : 23 : size_t offset = tag_data.sparse_offset;
2034 : 23 : size_t num_writes = ( remaining + chunk_size - 1 ) / chunk_size;
2035 [ - + ]: 23 : if( tag_data.max_num_ents )
2036 : : {
2037 [ # # ]: 0 : assert( tag_data.max_num_ents >= (unsigned long)remaining );
2038 : 0 : num_writes = ( tag_data.max_num_ents + chunk_size - 1 ) / chunk_size;
2039 : : }
2040 [ + - ]: 23 : Range::const_iterator iter = range.begin();
2041 [ + + ]: 46 : while( remaining )
2042 : : {
2043 : : (void)VALGRIND_MAKE_MEM_UNDEFINED( dataBuffer, bufferSize );
2044 : :
2045 : : // Write "chunk_size" blocks of data
2046 [ - + ]: 23 : size_t count = remaining > chunk_size ? chunk_size : remaining;
2047 : 23 : remaining -= count;
2048 : 23 : Range::const_iterator stop = iter;
2049 [ + - ]: 23 : stop += count;
2050 [ + - ]: 23 : Range tmp;
2051 [ + - ]: 23 : tmp.merge( iter, stop );
2052 : 23 : iter = stop;
2053 [ + - ][ - + ]: 23 : assert( tmp.size() == (unsigned)count );
2054 : :
2055 [ + - ]: 23 : rval = iFace->tag_get_by_ptr( tag_data.tag_id, tmp, junk, size_buffer );
2056 [ - + ][ # # ]: 23 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2057 : :
2058 : : // Calculate end indices
2059 [ + - ]: 23 : dbgOut.print( 3, " writing var-len tag offset chunk.\n" );
2060 [ + - ]: 23 : track.record_io( offset, count );
2061 [ + + ]: 206 : for( size_t i = 0; i < count; ++i )
2062 : : {
2063 : 183 : data_offset += size_buffer[i];
2064 : 183 : idx_buffer[i] = data_offset;
2065 : : }
2066 : :
2067 : : // Write
2068 [ + - ][ + - ]: 23 : mhdf_writeSparseTagIndicesWithOpt( idx_table, offset, count, MHDF_INDEX_TYPE, idx_buffer, writeProp, &status );
2069 [ + - ][ - + ]: 23 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2070 : :
2071 : 23 : offset += count;
2072 [ + - ]: 23 : --num_writes;
2073 : 23 : } // while (remaining)
2074 : :
2075 : : // Do empty writes if necessary for parallel collective IO
2076 [ - + ]: 23 : if( collectiveIO )
2077 : : {
2078 [ # # ]: 0 : while( num_writes-- )
2079 : : {
2080 [ # # ]: 0 : assert( writeProp != H5P_DEFAULT );
2081 [ # # ]: 0 : dbgOut.print( 3, " writing empty sparse tag entity chunk.\n" );
2082 [ # # ]: 0 : mhdf_writeSparseTagIndicesWithOpt( idx_table, offset, 0, id_type, 0, writeProp, &status );
2083 [ # # ][ # # ]: 0 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2084 : : }
2085 : : }
2086 : :
2087 [ + - ]: 23 : track.all_reduce();
2088 : 46 : return MB_SUCCESS;
2089 : : }
2090 : :
2091 : 23 : ErrorCode WriteHDF5::write_var_len_data( const TagDesc& tag_data, const Range& range, hid_t table, size_t table_size,
2092 : : bool handle_tag, hid_t hdf_type, int type_size, const char* name )
2093 : : {
2094 : : ErrorCode rval;
2095 : : mhdf_Status status;
2096 : :
2097 [ + - ]: 23 : CHECK_OPEN_HANDLES;
2098 [ + + ][ - + ]: 23 : assert( !handle_tag || sizeof( EntityHandle ) == type_size );
2099 : :
2100 [ + - ][ + - ]: 46 : std::string tname( name ? name : "<UNKNOWN TAG?>" );
2101 [ + - ]: 23 : tname += " - Values";
2102 [ + - ]: 46 : IODebugTrack track( debugTrack, tname, table_size );
2103 : :
2104 : 23 : const size_t buffer_size = bufferSize / type_size;
2105 : :
2106 : 23 : size_t num_writes = ( table_size + buffer_size - 1 ) / buffer_size;
2107 [ - + ]: 23 : if( collectiveIO )
2108 : : {
2109 [ # # ]: 0 : assert( tag_data.max_num_vals > 0 );
2110 : 0 : num_writes = ( tag_data.max_num_vals + buffer_size - 1 ) / buffer_size;
2111 : : }
2112 : :
2113 : 23 : unsigned char* buffer = (unsigned char*)dataBuffer;
2114 : 23 : const void* prev_data = 0; // Data left over from prev iteration
2115 : 23 : size_t prev_len = 0;
2116 [ + - ]: 23 : Range::const_iterator iter = range.begin();
2117 : 23 : long offset = tag_data.var_data_offset;
2118 [ + - ][ + - ]: 46 : while( prev_data || iter != range.end() )
[ + - ][ + + ]
[ + - ]
[ + + # # ]
2119 : : {
2120 : 23 : size_t count = 0;
2121 [ - + ]: 23 : if( prev_data )
2122 : : {
2123 : : size_t len;
2124 : 0 : const void* ptr = prev_data;
2125 [ # # ]: 0 : if( prev_len <= buffer_size )
2126 : : {
2127 : 0 : len = prev_len;
2128 : 0 : prev_data = 0;
2129 : 0 : prev_len = 0;
2130 : : }
2131 : : else
2132 : : {
2133 : 0 : len = buffer_size;
2134 : 0 : prev_data = ( (const char*)prev_data ) + buffer_size * type_size;
2135 : 0 : prev_len -= buffer_size;
2136 : : }
2137 : :
2138 [ # # ]: 0 : if( handle_tag )
2139 [ # # ]: 0 : convert_handle_tag( (const EntityHandle*)ptr, (EntityHandle*)buffer, len );
2140 : : else
2141 : 0 : memcpy( buffer, ptr, len * type_size );
2142 : : }
2143 : :
2144 [ + - ][ + - ]: 206 : for( ; count < buffer_size && iter != range.end(); ++iter )
[ + - ][ + - ]
[ + + ][ + - ]
[ + + # # ]
2145 : : {
2146 : : int len;
2147 : : const void* ptr;
2148 [ + - ][ + - ]: 183 : rval = iFace->tag_get_by_ptr( tag_data.tag_id, &*iter, 1, &ptr, &len );
2149 [ - + ][ # # ]: 183 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2150 : 183 : int bytes = len * type_size;
2151 [ - + ]: 183 : if( len + count > buffer_size )
2152 : : {
2153 : 0 : prev_len = len + count - buffer_size;
2154 : 0 : prev_data = ( (const char*)ptr ) + prev_len * type_size;
2155 : 0 : len = buffer_size - count;
2156 : : }
2157 : :
2158 [ + + ]: 183 : if( handle_tag )
2159 [ + - ]: 91 : convert_handle_tag( (const EntityHandle*)ptr, ( (EntityHandle*)buffer ) + count, len );
2160 : : else
2161 : 92 : memcpy( buffer + count * type_size, ptr, bytes );
2162 : 183 : count += len;
2163 : : }
2164 : :
2165 [ + - ]: 23 : track.record_io( offset, count );
2166 [ + - ]: 23 : mhdf_writeTagValuesWithOpt( table, offset, count, hdf_type, buffer, writeProp, &status );
2167 [ + - ][ - + ]: 23 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2168 : 23 : --num_writes;
2169 : : }
2170 : :
2171 : : // Do empty writes if necessary for parallel collective IO
2172 [ - + ]: 23 : if( collectiveIO )
2173 : : {
2174 [ # # ]: 0 : while( num_writes-- )
2175 : : {
2176 [ # # ]: 0 : assert( writeProp != H5P_DEFAULT );
2177 [ # # ]: 0 : dbgOut.print( 3, " writing empty var-len tag data chunk.\n" );
2178 [ # # ]: 0 : mhdf_writeTagValuesWithOpt( table, 0, 0, hdf_type, 0, writeProp, &status );
2179 [ # # ][ # # ]: 0 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2180 : : }
2181 : : }
2182 : :
2183 [ + - ]: 23 : track.all_reduce();
2184 : 46 : return MB_SUCCESS;
2185 : : }
2186 : :
2187 : 23 : ErrorCode WriteHDF5::write_var_len_tag( const TagDesc& tag_data, const std::string& name, DataType mb_data_type,
2188 : : hid_t hdf_type, int type_size )
2189 : : {
2190 : : ErrorCode rval;
2191 : : mhdf_Status status;
2192 : : hid_t tables[3];
2193 : : long table_size;
2194 : : long data_table_size;
2195 : :
2196 [ + - ]: 23 : CHECK_OPEN_HANDLES;
2197 : :
2198 : : // Get entities for which to write tag values
2199 [ + - ]: 46 : Range range;
2200 [ + - ]: 23 : rval = get_sparse_tagged_entities( tag_data, range );
2201 : :
2202 : : // Open tables to write info
2203 [ + - ]: 23 : mhdf_openSparseTagData( filePtr, name.c_str(), &table_size, &data_table_size, tables, &status );
2204 [ + - ][ - + ]: 23 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2205 [ + - ][ - + ]: 23 : assert( range.size() + tag_data.sparse_offset <= (unsigned long)table_size );
2206 : :
2207 : : // Write IDs for tagged entities
2208 [ + - ]: 23 : subState.start( "writing ids for var-len tag: ", name.c_str() );
2209 [ + - ]: 23 : rval = write_sparse_ids( tag_data, range, tables[0], table_size, name.c_str() );
2210 [ + - ]: 23 : subState.end( rval );
2211 [ - + ][ # # ]: 23 : CHK_MB_ERR_2( rval, tables, status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2212 [ + - ]: 23 : mhdf_closeData( filePtr, tables[0], &status );
2213 [ + - ][ - + ]: 23 : CHK_MHDF_ERR_2( status, tables + 1 );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2214 : :
2215 : : // Write offsets for tagged entities
2216 [ + - ]: 23 : subState.start( "writing indices for var-len tag: ", name.c_str() );
2217 [ + - ]: 23 : rval = write_var_len_indices( tag_data, range, tables[2], table_size, type_size, name.c_str() );
2218 [ + - ]: 23 : subState.end( rval );
2219 [ - + ][ # # ]: 23 : CHK_MB_ERR_1( rval, tables[1], status );
[ # # ][ # # ]
[ # # ]
2220 [ + - ]: 23 : mhdf_closeData( filePtr, tables[2], &status );
2221 [ + - ][ - + ]: 23 : CHK_MHDF_ERR_1( status, tables[1] );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2222 : :
2223 : : // Write the actual tag data
2224 [ + - ]: 23 : subState.start( "writing values for var-len tag: ", name.c_str() );
2225 : : rval = write_var_len_data( tag_data, range, tables[1], data_table_size, mb_data_type == MB_TYPE_HANDLE, hdf_type,
2226 [ + - ]: 23 : type_size, name.c_str() );
2227 [ + - ]: 23 : subState.end( rval );
2228 [ - + ][ # # ]: 23 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2229 [ + - ]: 23 : mhdf_closeData( filePtr, tables[1], &status );
2230 [ + - ][ - + ]: 23 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2231 : :
2232 : 46 : return MB_SUCCESS;
2233 : : }
2234 : :
2235 : 106 : ErrorCode WriteHDF5::write_dense_tag( const TagDesc& tag_data, const ExportSet& elem_data, const std::string& name,
2236 : : DataType mb_data_type, hid_t value_type, int value_type_size )
2237 : : {
2238 [ + - ]: 106 : CHECK_OPEN_HANDLES;
2239 : :
2240 : : // Open tables to write info
2241 : : mhdf_Status status;
2242 : : long table_size;
2243 [ + - ][ + - ]: 106 : hid_t table = mhdf_openDenseTagData( filePtr, name.c_str(), elem_data.name(), &table_size, &status );
2244 [ + - ][ - + ]: 106 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2245 [ + - ][ - + ]: 106 : assert( elem_data.range.size() + elem_data.offset <= (unsigned long)table_size );
2246 : :
2247 [ + - ][ + - ]: 212 : IODebugTrack track( debugTrack, name + " " + elem_data.name() + " Data", table_size );
[ + - ][ + - ]
[ + - ]
2248 : : ErrorCode rval = write_tag_values( tag_data.tag_id, table, elem_data.offset, elem_data.range, mb_data_type,
2249 [ + - ]: 106 : value_type, value_type_size, elem_data.max_num_ents, track );
2250 [ - + ][ # # ]: 106 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2251 [ + - ]: 106 : mhdf_closeData( filePtr, table, &status );
2252 [ + - ][ - + ]: 106 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2253 : :
2254 : 212 : return MB_SUCCESS;
2255 : : }
2256 : :
2257 : 201 : ErrorCode WriteHDF5::write_tag_values( Tag tag_id, hid_t data_table, unsigned long offset_in, const Range& range_in,
2258 : : DataType mb_data_type, hid_t value_type, int value_type_size,
2259 : : unsigned long max_num_ents, IODebugTrack& track )
2260 : : {
2261 : : mhdf_Status status;
2262 : :
2263 [ + - ]: 201 : CHECK_OPEN_HANDLES;
2264 : :
2265 : : // Set up data buffer for writing tag values
2266 : 201 : size_t chunk_size = bufferSize / value_type_size;
2267 [ - + ]: 201 : assert( chunk_size > 0 );
2268 : 201 : char* tag_buffer = (char*)dataBuffer;
2269 : :
2270 : : // Write the tag values
2271 [ + - ]: 201 : size_t remaining = range_in.size();
2272 : 201 : size_t offset = offset_in;
2273 [ + - ]: 201 : Range::const_iterator iter = range_in.begin();
2274 : 201 : long num_writes = ( remaining + chunk_size - 1 ) / chunk_size;
2275 [ + + ]: 201 : if( max_num_ents )
2276 : : {
2277 [ - + ]: 32 : assert( max_num_ents >= remaining );
2278 : 32 : num_writes = ( max_num_ents + chunk_size - 1 ) / chunk_size;
2279 : : }
2280 [ + + ]: 402 : while( remaining )
2281 : : {
2282 : : (void)VALGRIND_MAKE_MEM_UNDEFINED( dataBuffer, bufferSize );
2283 : :
2284 : : // Write "chunk_size" blocks of data
2285 [ - + ]: 201 : long count = (unsigned long)remaining > chunk_size ? chunk_size : remaining;
2286 : 201 : remaining -= count;
2287 : 201 : memset( tag_buffer, 0, count * value_type_size );
2288 : 201 : Range::const_iterator stop = iter;
2289 [ + - ]: 201 : stop += count;
2290 [ + - ]: 201 : Range range;
2291 [ + - ]: 201 : range.merge( iter, stop );
2292 : 201 : iter = stop;
2293 [ + - ][ - + ]: 201 : assert( range.size() == (unsigned)count );
2294 : :
2295 [ + - ]: 201 : ErrorCode rval = iFace->tag_get_data( tag_id, range, tag_buffer );
2296 [ - + ][ # # ]: 201 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2297 : :
2298 : : // Convert EntityHandles to file ids
2299 [ + + ]: 201 : if( mb_data_type == MB_TYPE_HANDLE )
2300 : : convert_handle_tag( reinterpret_cast< EntityHandle* >( tag_buffer ),
2301 [ + - ]: 20 : count * value_type_size / sizeof( EntityHandle ) );
2302 : :
2303 : : // Write the data
2304 [ + - ]: 201 : dbgOut.print( 2, " writing tag value chunk.\n" );
2305 [ + - ]: 201 : track.record_io( offset, count );
2306 [ - + ]: 201 : assert( value_type > 0 );
2307 [ + - ]: 201 : mhdf_writeTagValuesWithOpt( data_table, offset, count, value_type, tag_buffer, writeProp, &status );
2308 [ + - ][ - + ]: 201 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2309 : :
2310 : 201 : offset += count;
2311 [ + - ]: 201 : --num_writes;
2312 : 201 : } // while (remaining)
2313 : :
2314 : : // Do empty writes if necessary for parallel collective IO
2315 [ - + ]: 201 : if( collectiveIO )
2316 : : {
2317 [ # # ]: 0 : while( num_writes-- )
2318 : : {
2319 [ # # ]: 0 : assert( writeProp != H5P_DEFAULT );
2320 [ # # ]: 0 : dbgOut.print( 2, " writing empty tag value chunk.\n" );
2321 [ # # ]: 0 : assert( value_type > 0 );
2322 [ # # ]: 0 : mhdf_writeTagValuesWithOpt( data_table, offset, 0, value_type, 0, writeProp, &status );
2323 [ # # ][ # # ]: 0 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2324 : : }
2325 : : }
2326 : :
2327 [ + - ]: 201 : track.all_reduce();
2328 : 201 : return MB_SUCCESS;
2329 : : }
2330 : :
2331 : 39 : ErrorCode WriteHDF5::write_qa( const std::vector< std::string >& list )
2332 : : {
2333 : 39 : const char* app = "MOAB";
2334 : 39 : const char* vers = MOAB_VERSION;
2335 : : char date_str[64];
2336 : : char time_str[64];
2337 : :
2338 [ + - ]: 39 : CHECK_OPEN_HANDLES;
2339 : :
2340 [ - + ][ + - ]: 78 : std::vector< const char* > strs( list.size() ? list.size() : 4 );
2341 [ + - ]: 39 : if( list.size() == 0 )
2342 : : {
2343 : 39 : time_t t = time( NULL );
2344 : 39 : tm* lt = localtime( &t );
2345 : : #ifdef WIN32
2346 : : strftime( date_str, sizeof( date_str ), "%m/%d/%y", lt ); // VS 2008 does not support %D
2347 : : strftime( time_str, sizeof( time_str ), "%H:%M:%S", lt ); // VS 2008 does not support %T
2348 : : #else
2349 : 39 : strftime( date_str, sizeof( date_str ), "%D", lt );
2350 : 39 : strftime( time_str, sizeof( time_str ), "%T", lt );
2351 : : #endif
2352 : :
2353 [ + - ]: 39 : strs[0] = app;
2354 [ + - ]: 39 : strs[1] = vers;
2355 [ + - ]: 39 : strs[2] = date_str;
2356 [ + - ]: 39 : strs[3] = time_str;
2357 : : }
2358 : : else
2359 : : {
2360 [ # # ]: 0 : for( unsigned int i = 0; i < list.size(); ++i )
2361 [ # # ][ # # ]: 0 : strs[i] = list[i].c_str();
2362 : : }
2363 : :
2364 : : mhdf_Status status;
2365 [ + - ]: 39 : dbgOut.print( 2, " writing QA history.\n" );
2366 [ + - ][ + - ]: 39 : mhdf_writeHistory( filePtr, &strs[0], strs.size(), &status );
2367 [ + - ][ - + ]: 39 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2368 : :
2369 : 39 : return MB_SUCCESS;
2370 : : }
2371 : :
2372 : : /*
2373 : : ErrorCode WriteHDF5::register_known_tag_types(Interface* iface)
2374 : : {
2375 : : hid_t int4, double16;
2376 : : hsize_t dim[1];
2377 : : int error = 0;
2378 : : ErrorCode rval;
2379 : :
2380 : : dim[0] = 4;
2381 : : int4 = H5Tarray_create(H5T_NATIVE_INT, 1, dim, NULL);
2382 : :
2383 : : dim[0] = 16;
2384 : : double16 = H5Tarray_create(H5T_NATIVE_DOUBLE, 1, dim, NULL);
2385 : :
2386 : : if (int4 < 0 || double16 < 0)
2387 : : error = 1;
2388 : :
2389 : : struct { const char* name; hid_t type; } list[] = {
2390 : : { GLOBAL_ID_TAG_NAME, H5T_NATIVE_INT } ,
2391 : : { MATERIAL_SET_TAG_NAME, H5T_NATIVE_INT },
2392 : : { DIRICHLET_SET_TAG_NAME, H5T_NATIVE_INT },
2393 : : { NEUMANN_SET_TAG_NAME, H5T_NATIVE_INT },
2394 : : { HAS_MID_NODES_TAG_NAME, int4 },
2395 : : { GEOM_DIMENSION_TAG_NAME, H5T_NATIVE_INT },
2396 : : { MESH_TRANSFORM_TAG_NAME, double16 },
2397 : : { 0, 0 } };
2398 : :
2399 : : for (int i = 0; list[i].name; ++i) {
2400 : : if (list[i].type < 1) {
2401 : : ++error;
2402 : : continue;
2403 : : }
2404 : :
2405 : : Tag handle;
2406 : :
2407 : : std::string name("__hdf5_tag_type_");
2408 : : name += list[i].name;
2409 : :
2410 : : rval = iface->tag_get_handle(name.c_str(), handle);
2411 : : if (MB_TAG_NOT_FOUND == rval) {
2412 : : rval = iface->tag_create(name.c_str(), sizeof(hid_t), MB_TAG_SPARSE, handle, NULL);
2413 : : if (MB_SUCCESS != rval) {
2414 : : ++error;
2415 : : continue;
2416 : : }
2417 : :
2418 : : hid_t copy_id = H5Tcopy(list[i].type);
2419 : : const EntityHandle mesh = 0;
2420 : : rval = iface->tag_set_data(handle, &mesh, 1, ©_id);
2421 : : if (MB_SUCCESS != rval) {
2422 : : ++error;
2423 : : continue;
2424 : : }
2425 : : }
2426 : : }
2427 : :
2428 : : H5Tclose(int4);
2429 : : H5Tclose(double16);
2430 : : return error ? MB_FAILURE : MB_SUCCESS;
2431 : : }
2432 : : */
2433 : :
2434 : 39 : ErrorCode WriteHDF5::gather_tags( const Tag* user_tag_list, int num_tags )
2435 : : {
2436 : : ErrorCode result;
2437 [ + - ]: 39 : std::vector< Tag > tag_list;
2438 : 39 : std::vector< Tag >::iterator t_itor;
2439 [ + - ]: 78 : Range range;
2440 : :
2441 : : // Get list of Tags to write
2442 [ + - ]: 39 : result = writeUtil->get_tag_list( tag_list, user_tag_list, num_tags );
2443 [ - + ][ # # ]: 39 : CHK_MB_ERR_0( result );
[ # # ][ # # ]
2444 : :
2445 : : // Get list of tags
2446 [ + - ][ + - ]: 386 : for( t_itor = tag_list.begin(); t_itor != tag_list.end(); ++t_itor )
[ + + ]
2447 : : {
2448 : : // Add tag to export list
2449 [ + - ]: 347 : TagDesc tag_data;
2450 : 347 : tag_data.write_sparse = false;
2451 [ + - ]: 347 : tag_data.tag_id = *t_itor;
2452 : 347 : tag_data.sparse_offset = 0;
2453 : 347 : tag_data.var_data_offset = 0;
2454 : 347 : tag_data.max_num_ents = 0;
2455 : 347 : tag_data.max_num_vals = 0;
2456 [ + - ]: 347 : tagList.push_back( tag_data );
2457 : 347 : }
2458 : :
2459 : 78 : return MB_SUCCESS;
2460 : : }
2461 : :
2462 : : // If we support parallel, then this function will have been
2463 : : // overridden with an alternate version in WriteHDF5Parallel
2464 : : // that supports parallel I/O. If we're here
2465 : : // then MOAB was not built with support for parallel HDF5 I/O.
2466 : 0 : ErrorCode WriteHDF5::parallel_create_file( const char* /* filename */, bool /* overwrite */,
2467 : : const std::vector< std::string >& /* qa_records */,
2468 : : const FileOptions& /* opts */, const Tag* /* tag_list */, int /* num_tags */,
2469 : : int /* dimension */, double* /* times */ )
2470 : : {
2471 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_NOT_IMPLEMENTED, "WriteHDF5 does not support parallel writing" );
[ # # ][ # # ]
[ # # ]
2472 : : }
2473 : :
2474 : 39 : ErrorCode WriteHDF5::serial_create_file( const char* filename, bool overwrite,
2475 : : const std::vector< std::string >& qa_records, const Tag* user_tag_list,
2476 : : int num_user_tags, int dimension )
2477 : : {
2478 : : long first_id;
2479 : : mhdf_Status status;
2480 : : hid_t handle;
2481 [ + - ]: 39 : std::list< ExportSet >::iterator ex_itor;
2482 : : ErrorCode rval;
2483 : :
2484 [ + - ]: 39 : topState.start( "creating file" );
2485 : :
2486 : : const char* type_names[MBMAXTYPE];
2487 : 39 : memset( type_names, 0, MBMAXTYPE * sizeof( char* ) );
2488 [ + - ][ + + ]: 429 : for( EntityType i = MBEDGE; i < MBENTITYSET; ++i )
2489 [ + - ]: 390 : type_names[i] = CN::EntityTypeName( i );
2490 : :
2491 : : // Create the file
2492 [ + - ]: 39 : filePtr = mhdf_createFile( filename, overwrite, type_names, MBMAXTYPE, id_type, &status );
2493 [ + - ][ - + ]: 39 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2494 [ - + ]: 39 : assert( !!filePtr );
2495 : :
2496 [ + - ]: 39 : rval = write_qa( qa_records );
2497 [ - + ][ # # ]: 39 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2498 : :
2499 : : // Create node table
2500 [ + - ][ + + ]: 39 : if( nodeSet.range.size() )
2501 : : {
2502 [ + - ]: 38 : nodeSet.total_num_ents = nodeSet.range.size();
2503 [ + - ]: 38 : handle = mhdf_createNodeCoords( filePtr, dimension, nodeSet.total_num_ents, &first_id, &status );
2504 [ + - ][ - + ]: 38 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2505 [ + - ]: 38 : mhdf_closeData( filePtr, handle, &status );
2506 [ + - ][ - + ]: 38 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2507 : 38 : nodeSet.first_id = (wid_t)first_id;
2508 [ + - ]: 38 : rval = assign_ids( nodeSet.range, nodeSet.first_id );
2509 [ - + ][ # # ]: 38 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2510 : : }
2511 : : else
2512 : : {
2513 : 1 : nodeSet.first_id = std::numeric_limits< wid_t >::max();
2514 : : }
2515 : 39 : nodeSet.offset = 0;
2516 : :
2517 : : // Create element tables
2518 [ + - ][ + - ]: 91 : for( ex_itor = exportList.begin(); ex_itor != exportList.end(); ++ex_itor )
[ + + ]
2519 : : {
2520 [ + - ][ + - ]: 52 : ex_itor->total_num_ents = ex_itor->range.size();
[ + - ]
2521 [ + - ][ + - ]: 52 : rval = create_elem_table( *ex_itor, ex_itor->total_num_ents, first_id );
[ + - ]
2522 [ - + ][ # # ]: 52 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2523 : :
2524 [ + - ]: 52 : ex_itor->first_id = (wid_t)first_id;
2525 [ + - ]: 52 : ex_itor->offset = 0;
2526 [ + - ][ + - ]: 52 : rval = assign_ids( ex_itor->range, ex_itor->first_id );
[ + - ]
2527 [ - + ][ # # ]: 52 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2528 : : }
2529 : : // Create set tables
2530 [ + - ]: 39 : writeSets = !setSet.range.empty();
2531 [ + - ]: 39 : if( writeSets )
2532 : : {
2533 : : long contents_len, children_len, parents_len;
2534 : :
2535 [ + - ]: 39 : setSet.total_num_ents = setSet.range.size();
2536 : 39 : setSet.max_num_ents = setSet.total_num_ents;
2537 [ + - ]: 39 : rval = create_set_meta( setSet.total_num_ents, first_id );
2538 [ - + ][ # # ]: 39 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2539 : :
2540 : 39 : setSet.first_id = (wid_t)first_id;
2541 [ + - ]: 39 : rval = assign_ids( setSet.range, setSet.first_id );
2542 [ - + ][ # # ]: 39 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2543 : :
2544 [ + - ]: 39 : rval = count_set_size( setSet.range, contents_len, children_len, parents_len );
2545 [ - + ][ # # ]: 39 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2546 : :
2547 [ + - ]: 39 : rval = create_set_tables( contents_len, children_len, parents_len );
2548 [ - + ][ # # ]: 39 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2549 : :
2550 : 39 : setSet.offset = 0;
2551 : 39 : setContentsOffset = 0;
2552 : 39 : setChildrenOffset = 0;
2553 : 39 : setParentsOffset = 0;
2554 : 39 : writeSetContents = !!contents_len;
2555 : 39 : writeSetChildren = !!children_len;
2556 : 39 : writeSetParents = !!parents_len;
2557 : :
2558 : 39 : maxNumSetContents = contents_len;
2559 : 39 : maxNumSetChildren = children_len;
2560 : 39 : maxNumSetParents = parents_len;
2561 : : } // if (!setSet.range.empty())
2562 : :
2563 : : // Create adjacency table after set table, because sets do not have yet an id
2564 : : // some entities are adjacent to sets (exodus?)
2565 : : // Create node adjacency table
2566 : : wid_t num_adjacencies;
2567 : : #ifdef MB_H5M_WRITE_NODE_ADJACENCIES
2568 : : rval = count_adjacencies( nodeSet.range, num_adjacencies );
2569 : : CHK_MB_ERR_0( rval );
2570 : : nodeSet.adj_offset = 0;
2571 : : nodeSet.max_num_adjs = num_adjacencies;
2572 : : if( num_adjacencies > 0 )
2573 : : {
2574 : : handle = mhdf_createAdjacency( filePtr, mhdf_node_type_handle(), num_adjacencies, &status );
2575 : : CHK_MHDF_ERR_0( status );
2576 : : mhdf_closeData( filePtr, handle, &status );
2577 : : }
2578 : : #endif
2579 : :
2580 : : // Create element adjacency tables
2581 [ + - ][ + - ]: 91 : for( ex_itor = exportList.begin(); ex_itor != exportList.end(); ++ex_itor )
[ + + ]
2582 : : {
2583 [ + - ][ + - ]: 52 : rval = count_adjacencies( ex_itor->range, num_adjacencies );
2584 [ - + ][ # # ]: 52 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2585 : :
2586 [ + - ]: 52 : ex_itor->adj_offset = 0;
2587 [ + - ]: 52 : ex_itor->max_num_adjs = num_adjacencies;
2588 [ + + ]: 52 : if( num_adjacencies > 0 )
2589 : : {
2590 [ + - ][ + - ]: 2 : handle = mhdf_createAdjacency( filePtr, ex_itor->name(), num_adjacencies, &status );
[ + - ]
2591 [ + - ][ - + ]: 2 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2592 [ + - ]: 2 : mhdf_closeData( filePtr, handle, &status );
2593 : : }
2594 : : }
2595 : :
2596 [ + - ]: 39 : dbgOut.tprint( 1, "Gathering Tags\n" );
2597 : :
2598 [ + - ]: 39 : rval = gather_tags( user_tag_list, num_user_tags );
2599 [ - + ][ # # ]: 39 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2600 : :
2601 : : // Create the tags and tag data tables
2602 : 39 : std::list< TagDesc >::iterator tag_iter = tagList.begin();
2603 [ + - ][ + - ]: 386 : for( ; tag_iter != tagList.end(); ++tag_iter )
[ + + ]
2604 : : {
2605 : : // As we haven't yet added any ExportSets for which to write
2606 : : // dense tag data to the TagDesc struct pointed to by
2607 : : // tag_iter, this call will initially return all tagged entities
2608 : : // in the set of entities to be written.
2609 [ + - ]: 347 : Range range;
2610 [ + - ][ + - ]: 347 : rval = get_sparse_tagged_entities( *tag_iter, range );
2611 [ - + ][ # # ]: 347 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2612 : :
2613 : : int s;
2614 [ + - ][ + - ]: 347 : bool var_len = ( MB_VARIABLE_DATA_LENGTH == iFace->tag_get_length( tag_iter->tag_id, s ) );
2615 : :
2616 : : // Determine which ExportSets we want to write dense
2617 : : // data for. We never write dense data for variable-length
2618 : : // tag data.
2619 [ + + ][ + - ]: 347 : if( !var_len && writeTagDense )
2620 : : {
2621 : : // Check if we want to write this tag in dense format even if not
2622 : : // all of the entities have a tag value. The criterion of this
2623 : : // is that the tag be dense, have a default value, and have at
2624 : : // least 2/3 of the entities tagged.
2625 : 323 : bool prefer_dense = false;
2626 : : TagType type;
2627 [ + - ][ + - ]: 323 : rval = iFace->tag_get_type( tag_iter->tag_id, type );
2628 [ - + ][ # # ]: 323 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2629 [ + + ]: 323 : if( MB_TAG_DENSE == type )
2630 : : {
2631 : 63 : const void* defval = 0;
2632 [ + - ][ + - ]: 63 : rval = iFace->tag_get_default_value( tag_iter->tag_id, defval, s );
2633 [ + + ]: 63 : if( MB_SUCCESS == rval ) prefer_dense = true;
2634 : : }
2635 : :
2636 [ + - ][ + + ]: 323 : if( check_dense_format_tag( nodeSet, range, prefer_dense ) )
2637 : : {
2638 [ + - ]: 36 : range -= nodeSet.range;
2639 [ + - ][ + - ]: 36 : tag_iter->dense_list.push_back( nodeSet );
2640 : : }
2641 : :
2642 [ + - ]: 323 : std::list< ExportSet >::const_iterator ex = exportList.begin();
2643 [ + - ][ + - ]: 795 : for( ; ex != exportList.end(); ++ex )
[ + - ][ + + ]
2644 : : {
2645 [ + - ][ + - ]: 472 : if( check_dense_format_tag( *ex, range, prefer_dense ) )
[ + + ]
2646 : : {
2647 [ + - ][ + - ]: 38 : range -= ex->range;
2648 [ + - ][ + - ]: 38 : tag_iter->dense_list.push_back( *ex );
[ + - ]
2649 : : }
2650 : : }
2651 : :
2652 [ + - ][ + + ]: 323 : if( check_dense_format_tag( setSet, range, prefer_dense ) )
2653 : : {
2654 [ + - ]: 32 : range -= setSet.range;
2655 [ + - ][ + - ]: 323 : tag_iter->dense_list.push_back( setSet );
2656 : : }
2657 : : }
2658 : :
2659 [ + - ][ + - ]: 347 : tag_iter->write_sparse = !range.empty();
2660 : :
2661 : 347 : unsigned long var_len_total = 0;
2662 [ + + ]: 347 : if( var_len )
2663 : : {
2664 [ + - ][ + - ]: 24 : rval = get_tag_data_length( *tag_iter, range, var_len_total );
2665 [ - + ][ # # ]: 24 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2666 : : }
2667 : :
2668 [ + - ][ + - ]: 347 : rval = create_tag( *tag_iter, range.size(), var_len_total );
[ + - ]
2669 [ - + ][ # # ]: 347 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
[ + - ]
2670 : 347 : } // for (tags)
2671 : :
2672 [ + - ]: 39 : topState.end();
2673 : 39 : return MB_SUCCESS;
2674 : : }
2675 : :
2676 : 1118 : bool WriteHDF5::check_dense_format_tag( const ExportSet& ents, const Range& all_tagged, bool prefer_dense )
2677 : : {
2678 : : // If there are no tagged entities, then don't write anything
2679 [ + - ][ + + ]: 1118 : if( ents.range.empty() ) return false;
2680 : :
2681 : : // If all of the entities are tagged, then write in dense format
2682 [ + - ][ + + ]: 1110 : if( all_tagged.contains( ents.range ) ) return true;
2683 : :
2684 : : // Unless asked for more lenient choice of dense format, return false
2685 [ + + ]: 1031 : if( !prefer_dense ) return false;
2686 : :
2687 : : // If we're being lenient about choosing dense format, then
2688 : : // return true if at least 2/3 of the entities are tagged.
2689 [ + - ]: 84 : Range xsect = intersect( setSet.range, all_tagged );
2690 [ + - ][ + - ]: 84 : if( 3 * xsect.size() >= 2 * setSet.range.size() ) return true;
[ + + ]
2691 : :
2692 : 1118 : return false;
2693 : : }
2694 : :
2695 : 52 : ErrorCode WriteHDF5::count_adjacencies( const Range& set, wid_t& result )
2696 : : {
2697 : : ErrorCode rval;
2698 [ + - ]: 52 : std::vector< wid_t > adj_list;
2699 [ + - ]: 52 : Range::const_iterator iter = set.begin();
2700 [ + - ]: 52 : const Range::const_iterator end = set.end();
2701 : 52 : result = 0;
2702 [ + - ][ + - ]: 37108 : for( ; iter != end; ++iter )
[ + + ]
2703 : : {
2704 : 37056 : adj_list.clear();
2705 [ + - ][ + - ]: 37056 : rval = get_adjacencies( *iter, adj_list );
2706 [ - + ][ # # ]: 37056 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2707 : :
2708 [ + + ]: 37056 : if( adj_list.size() > 0 ) result += 2 + adj_list.size();
2709 : : }
2710 : :
2711 : 52 : return MB_SUCCESS;
2712 : : }
2713 : :
2714 : 52 : ErrorCode WriteHDF5::create_elem_table( const ExportSet& block, long num_entities, long& first_id_out )
2715 : : {
2716 : : mhdf_Status status;
2717 : : hid_t handle;
2718 : :
2719 [ + - ]: 52 : CHECK_OPEN_HANDLES;
2720 : :
2721 [ + - ][ + - ]: 52 : mhdf_addElement( filePtr, block.name(), block.type, &status );
2722 [ + - ][ - + ]: 52 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2723 : :
2724 [ + - ][ + - ]: 52 : handle = mhdf_createConnectivity( filePtr, block.name(), block.num_nodes, num_entities, &first_id_out, &status );
2725 [ + - ][ - + ]: 52 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2726 [ + - ]: 52 : mhdf_closeData( filePtr, handle, &status );
2727 [ + - ][ - + ]: 52 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2728 : :
2729 : 52 : return MB_SUCCESS;
2730 : : }
2731 : :
2732 : 39 : ErrorCode WriteHDF5::count_set_size( const Range& sets, long& contents_length_out, long& children_length_out,
2733 : : long& parents_length_out )
2734 : : {
2735 : : ErrorCode rval;
2736 [ + - ]: 39 : Range set_contents;
2737 : : long contents_length_set, children_length_set, parents_length_set;
2738 : : unsigned long flags;
2739 [ + - ]: 78 : std::vector< wid_t > set_contents_ids;
2740 [ + - ]: 39 : std::vector< SpecialSetData >::const_iterator si = specialSets.begin();
2741 : :
2742 : 39 : contents_length_out = 0;
2743 : 39 : children_length_out = 0;
2744 : 39 : parents_length_out = 0;
2745 : :
2746 [ + - ][ + - ]: 522 : for( Range::const_iterator iter = sets.begin(); iter != sets.end(); ++iter )
[ + - ][ + - ]
[ + + ]
2747 : : {
2748 [ + - ][ - + ]: 483 : while( si != specialSets.end() && si->setHandle < *iter )
[ # # ][ # # ]
[ # # ][ + - ]
[ - + # # ]
2749 [ # # ]: 0 : ++si;
2750 : :
2751 [ + - ][ - + ]: 483 : if( si != specialSets.end() && si->setHandle == *iter )
[ # # ][ # # ]
[ # # ][ + - ]
[ - + # # ]
2752 : : {
2753 [ # # ]: 0 : contents_length_out += si->contentIds.size();
2754 [ # # ]: 0 : children_length_out += si->childIds.size();
2755 [ # # ]: 0 : parents_length_out += si->parentIds.size();
2756 [ # # ]: 0 : ++si;
2757 : 0 : continue;
2758 : : }
2759 : :
2760 [ + - ][ + - ]: 483 : rval = get_set_info( *iter, contents_length_set, children_length_set, parents_length_set, flags );
2761 [ - + ][ # # ]: 483 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2762 : :
2763 : : // Check if can and should compress as ranges
2764 [ + + ][ + + ]: 483 : if( !( flags & MESHSET_ORDERED ) && contents_length_set )
2765 : : {
2766 [ + - ]: 218 : set_contents.clear();
2767 [ + - ][ + - ]: 218 : rval = iFace->get_entities_by_handle( *iter, set_contents, false );
2768 [ - + ][ # # ]: 218 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2769 : :
2770 : : bool blocked_list;
2771 [ + - ]: 218 : rval = range_to_blocked_list( set_contents, set_contents_ids, blocked_list );
2772 [ - + ][ # # ]: 218 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2773 : :
2774 [ + + ]: 218 : if( blocked_list )
2775 : : {
2776 [ - + ]: 105 : assert( set_contents_ids.size() % 2 == 0 );
2777 : 218 : contents_length_set = set_contents_ids.size();
2778 : : }
2779 : : }
2780 : :
2781 : 483 : contents_length_out += contents_length_set;
2782 : 483 : children_length_out += children_length_set;
2783 : 483 : parents_length_out += parents_length_set;
2784 : : }
2785 : :
2786 : 78 : return MB_SUCCESS;
2787 : : }
2788 : :
2789 : 39 : ErrorCode WriteHDF5::create_set_meta( long num_sets, long& first_id_out )
2790 : : {
2791 : : hid_t handle;
2792 : : mhdf_Status status;
2793 : :
2794 [ + - ]: 39 : CHECK_OPEN_HANDLES;
2795 : :
2796 [ + - ]: 39 : handle = mhdf_createSetMeta( filePtr, num_sets, &first_id_out, &status );
2797 [ + - ][ - + ]: 39 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2798 [ + - ]: 39 : mhdf_closeData( filePtr, handle, &status );
2799 : :
2800 : 39 : return MB_SUCCESS;
2801 : : }
2802 : :
2803 : 0 : WriteHDF5::SpecialSetData* WriteHDF5::find_set_data( EntityHandle h )
2804 : : {
2805 [ # # ]: 0 : SpecialSetData tmp;
2806 : 0 : tmp.setHandle = h;
2807 : 0 : std::vector< SpecialSetData >::iterator i;
2808 [ # # ]: 0 : i = std::lower_bound( specialSets.begin(), specialSets.end(), tmp, SpecSetLess() );
2809 [ # # ][ # # ]: 0 : return ( i == specialSets.end() || i->setHandle != h ) ? 0 : &*i;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2810 : : }
2811 : :
2812 : 39 : ErrorCode WriteHDF5::create_set_tables( long num_set_contents, long num_set_children, long num_set_parents )
2813 : : {
2814 : : hid_t handle;
2815 : : mhdf_Status status;
2816 : :
2817 [ + - ]: 39 : CHECK_OPEN_HANDLES;
2818 : :
2819 [ + + ]: 39 : if( num_set_contents > 0 )
2820 : : {
2821 [ + - ]: 38 : handle = mhdf_createSetData( filePtr, num_set_contents, &status );
2822 [ + - ][ - + ]: 38 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2823 [ + - ]: 38 : mhdf_closeData( filePtr, handle, &status );
2824 : : }
2825 : :
2826 [ + + ]: 39 : if( num_set_children > 0 )
2827 : : {
2828 [ + - ]: 16 : handle = mhdf_createSetChildren( filePtr, num_set_children, &status );
2829 [ + - ][ - + ]: 16 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2830 [ + - ]: 16 : mhdf_closeData( filePtr, handle, &status );
2831 : : }
2832 : :
2833 [ + + ]: 39 : if( num_set_parents > 0 )
2834 : : {
2835 [ + - ]: 15 : handle = mhdf_createSetParents( filePtr, num_set_parents, &status );
2836 [ + - ][ - + ]: 15 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2837 [ + - ]: 15 : mhdf_closeData( filePtr, handle, &status );
2838 : : }
2839 : :
2840 : 39 : return MB_SUCCESS;
2841 : : }
2842 : :
2843 : 694 : ErrorCode WriteHDF5::get_tag_size( Tag tag, DataType& moab_type, int& num_bytes, int& type_size, int& array_length,
2844 : : mhdf_TagDataType& file_type, hid_t& hdf_type )
2845 : : {
2846 : : ErrorCode rval;
2847 : : Tag type_handle;
2848 [ + - ][ + - ]: 1388 : std::string tag_name, tag_type_name;
2849 : :
2850 [ + - ]: 1388 : CHECK_OPEN_HANDLES;
2851 : :
2852 : : // We return NULL for hdf_type if it can be determined from
2853 : : // the file_type. The only case where it is non-zero is
2854 : : // if the user specified a specific type via a mesh tag.
2855 : 694 : hdf_type = (hid_t)0;
2856 : 694 : bool close_hdf_type = false;
2857 : :
2858 [ + - ]: 694 : rval = iFace->tag_get_data_type( tag, moab_type );
2859 [ - + ][ # # ]: 694 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2860 [ + - ]: 694 : rval = iFace->tag_get_length( tag, array_length );
2861 [ + + ]: 694 : if( MB_VARIABLE_DATA_LENGTH == rval ) { array_length = MB_VARIABLE_LENGTH; }
2862 [ - + ]: 646 : else if( MB_SUCCESS != rval )
2863 : 0 : return error( rval );
2864 [ + - ]: 694 : rval = iFace->tag_get_bytes( tag, num_bytes );
2865 [ + + ]: 694 : if( MB_VARIABLE_DATA_LENGTH == rval )
2866 : 48 : num_bytes = MB_VARIABLE_LENGTH;
2867 [ - + ]: 646 : else if( MB_SUCCESS != rval )
2868 : 0 : return error( rval );
2869 : :
2870 [ + + - + : 694 : switch( moab_type )
+ - ]
2871 : : {
2872 : : case MB_TYPE_INTEGER:
2873 : 504 : type_size = sizeof( int );
2874 : 504 : file_type = mhdf_INTEGER;
2875 [ + - ]: 504 : hdf_type = H5T_NATIVE_INT;
2876 : 504 : close_hdf_type = false;
2877 : 504 : break;
2878 : : case MB_TYPE_DOUBLE:
2879 : 62 : type_size = sizeof( double );
2880 : 62 : file_type = mhdf_FLOAT;
2881 [ + - ]: 62 : hdf_type = H5T_NATIVE_DOUBLE;
2882 : 62 : close_hdf_type = false;
2883 : 62 : break;
2884 : : case MB_TYPE_BIT:
2885 : 0 : type_size = sizeof( bool );
2886 : 0 : file_type = mhdf_BITFIELD;
2887 [ # # ]: 0 : assert( array_length <= 8 );
2888 [ # # ][ # # ]: 0 : hdf_type = H5Tcopy( H5T_NATIVE_B8 );
2889 [ # # ]: 0 : H5Tset_precision( hdf_type, array_length );
2890 : 0 : close_hdf_type = true;
2891 : 0 : break;
2892 : : case MB_TYPE_HANDLE:
2893 : 94 : type_size = sizeof( EntityHandle );
2894 : 94 : file_type = mhdf_ENTITY_ID;
2895 : 94 : hdf_type = id_type;
2896 : 94 : close_hdf_type = false;
2897 : 94 : break;
2898 : : case MB_TYPE_OPAQUE:
2899 : 34 : file_type = mhdf_OPAQUE;
2900 [ + - ]: 34 : rval = iFace->tag_get_name( tag, tag_name );
2901 [ - + ][ # # ]: 34 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
2902 [ + - ]: 34 : tag_type_name = "__hdf5_tag_type_";
2903 [ + - ]: 34 : tag_type_name += tag_name;
2904 [ + - ]: 34 : rval = iFace->tag_get_handle( tag_type_name.c_str(), 0, MB_TYPE_OPAQUE, type_handle, MB_TAG_ANY );
2905 [ + - ]: 34 : if( MB_TAG_NOT_FOUND == rval )
2906 : : {
2907 [ + + ]: 34 : if( num_bytes == MB_VARIABLE_LENGTH )
2908 : 2 : type_size = 1;
2909 : : else
2910 : 32 : type_size = num_bytes;
2911 [ + - ]: 34 : hdf_type = H5Tcreate( H5T_OPAQUE, type_size );
2912 : 34 : close_hdf_type = true;
2913 : : }
2914 [ # # ]: 0 : else if( MB_SUCCESS == rval )
2915 : : {
2916 : : int hsize;
2917 [ # # ]: 0 : rval = iFace->tag_get_bytes( type_handle, hsize );
2918 [ # # ]: 0 : if( hsize != sizeof( hid_t ) ) return error( MB_FAILURE );
2919 : :
2920 : 0 : const EntityHandle root = 0;
2921 [ # # ]: 0 : rval = iFace->tag_get_data( type_handle, &root, 1, &hdf_type );
2922 [ # # ]: 0 : if( rval != MB_SUCCESS ) return error( rval );
2923 : :
2924 [ # # ]: 0 : type_size = H5Tget_size( hdf_type );
2925 [ # # ]: 0 : if( type_size != num_bytes ) return error( MB_FAILURE );
2926 : :
2927 : 0 : close_hdf_type = false;
2928 : : }
2929 : : else
2930 : 0 : return error( rval );
2931 : 34 : num_bytes = array_length;
2932 [ + + ]: 34 : array_length = ( num_bytes == MB_VARIABLE_LENGTH ) ? MB_VARIABLE_LENGTH : 1;
2933 : 34 : break;
2934 : : default:
2935 : 0 : break;
2936 : : }
2937 : :
2938 [ - + ][ # # ]: 646 : assert( num_bytes == MB_VARIABLE_LENGTH || ( moab_type == MB_TYPE_BIT && num_bytes == 1 ) ||
[ - + ]
2939 [ + + ]: 694 : array_length * type_size == num_bytes );
2940 : :
2941 [ + + ]: 694 : if( num_bytes == MB_VARIABLE_LENGTH )
2942 : : {
2943 : 48 : array_length = MB_VARIABLE_LENGTH;
2944 [ + + ]: 48 : if( !close_hdf_type )
2945 : : {
2946 [ + - ]: 46 : hdf_type = H5Tcopy( hdf_type );
2947 : : // close_hdf_type = true;
2948 : : }
2949 : : }
2950 [ + + ][ + - ]: 646 : else if( array_length > 1 && moab_type != MB_TYPE_BIT )
2951 : : {
2952 : 66 : hsize_t len = array_length;
2953 : : #if defined( H5Tarray_create_vers ) && ( H5Tarray_create_vers > 1 )
2954 [ + - ]: 66 : hid_t temp_id = H5Tarray_create2( hdf_type, 1, &len );
2955 : : #else
2956 : : hid_t temp_id = H5Tarray_create( hdf_type, 1, &len, NULL );
2957 : : #endif
2958 [ - + ][ # # ]: 66 : if( close_hdf_type ) H5Tclose( hdf_type );
2959 : 66 : hdf_type = temp_id;
2960 : : }
2961 [ + + ]: 580 : else if( !close_hdf_type )
2962 : : {
2963 [ + - ]: 548 : hdf_type = H5Tcopy( hdf_type );
2964 : : // close_hdf_type = true;
2965 : : }
2966 : :
2967 : 1388 : return MB_SUCCESS;
2968 : : }
2969 : :
2970 : 24 : ErrorCode WriteHDF5::get_tag_data_length( const TagDesc& tag_info, const Range& range, unsigned long& result )
2971 : : {
2972 : : ErrorCode rval;
2973 : 24 : result = 0;
2974 : :
2975 : : // Split buffer into two pieces, one for pointers and one for sizes
2976 : : size_t step, remaining;
2977 : 24 : step = bufferSize / ( sizeof( int ) + sizeof( void* ) );
2978 : 24 : const void** ptr_buffer = reinterpret_cast< const void** >( dataBuffer );
2979 : 24 : int* size_buffer = reinterpret_cast< int* >( ptr_buffer + step );
2980 [ + - ]: 24 : Range subrange;
2981 [ + - ]: 24 : Range::const_iterator iter = range.begin();
2982 [ + - ][ - + ]: 24 : for( remaining = range.size(); remaining >= step; remaining -= step )
2983 : : {
2984 : : // Get subset of range containing 'count' entities
2985 : 0 : Range::const_iterator end = iter;
2986 [ # # ]: 0 : end += step;
2987 [ # # ]: 0 : subrange.clear();
2988 [ # # ]: 0 : subrange.merge( iter, end );
2989 : 0 : iter = end;
2990 : : // Get tag sizes for entities
2991 [ # # ]: 0 : rval = iFace->tag_get_by_ptr( tag_info.tag_id, subrange, ptr_buffer, size_buffer );
2992 [ # # ]: 0 : if( MB_SUCCESS != rval ) return error( rval );
2993 : : // Sum lengths
2994 [ # # ]: 0 : for( size_t i = 0; i < step; ++i )
2995 : 0 : result += size_buffer[i];
2996 : : }
2997 : : // Process remaining
2998 [ + - ]: 24 : subrange.clear();
2999 [ + - ][ + - ]: 24 : subrange.merge( iter, range.end() );
3000 [ + - ][ - + ]: 24 : assert( subrange.size() == remaining );
3001 [ + - ]: 24 : rval = iFace->tag_get_by_ptr( tag_info.tag_id, subrange, ptr_buffer, size_buffer );
3002 [ - + ]: 24 : if( MB_SUCCESS != rval ) return error( rval );
3003 [ + + ]: 207 : for( size_t i = 0; i < remaining; ++i )
3004 : 183 : result += size_buffer[i];
3005 : :
3006 : 24 : return MB_SUCCESS;
3007 : : }
3008 : :
3009 : 347 : ErrorCode WriteHDF5::create_tag( const TagDesc& tag_data, unsigned long num_sparse_entities,
3010 : : unsigned long data_table_size )
3011 : : {
3012 : : TagType mb_storage;
3013 : : DataType mb_type;
3014 : : mhdf_TagDataType mhdf_type;
3015 : : int tag_bytes, type_size, num_vals, storage;
3016 : 347 : hid_t hdf_type = (hid_t)0;
3017 : : hid_t handles[3];
3018 [ + - ]: 347 : std::string tag_name;
3019 : : ErrorCode rval;
3020 : : mhdf_Status status;
3021 : :
3022 [ + - ]: 694 : CHECK_OPEN_HANDLES;
3023 : :
3024 : : // Get tag properties
3025 [ + - ]: 347 : rval = iFace->tag_get_type( tag_data.tag_id, mb_storage );
3026 [ - + ][ # # ]: 347 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
3027 [ + + - - : 347 : switch( mb_storage )
- ]
3028 : : {
3029 : : case MB_TAG_DENSE:
3030 : 63 : storage = mhdf_DENSE_TYPE;
3031 : 63 : break;
3032 : : case MB_TAG_SPARSE:
3033 : 284 : storage = mhdf_SPARSE_TYPE;
3034 : 284 : break;
3035 : : case MB_TAG_BIT:
3036 : 0 : storage = mhdf_BIT_TYPE;
3037 : 0 : break;
3038 : : case MB_TAG_MESH:
3039 : 0 : storage = mhdf_MESH_TYPE;
3040 : 0 : break;
3041 : : default:
3042 : 0 : return error( MB_FAILURE );
3043 : : }
3044 [ + - ]: 347 : rval = iFace->tag_get_name( tag_data.tag_id, tag_name );
3045 [ - + ][ # # ]: 347 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
3046 [ + - ]: 347 : rval = get_tag_size( tag_data.tag_id, mb_type, tag_bytes, type_size, num_vals, mhdf_type, hdf_type );
3047 [ - + ][ # # ]: 347 : CHK_MB_ERR_0( rval );
[ # # ][ # # ]
3048 : :
3049 : : // Get default value
3050 : : const void *def_value, *mesh_value;
3051 : : int def_val_len, mesh_val_len;
3052 [ + - ]: 347 : rval = iFace->tag_get_default_value( tag_data.tag_id, def_value, def_val_len );
3053 [ + + ]: 347 : if( MB_ENTITY_NOT_FOUND == rval )
3054 : : {
3055 : 119 : def_value = 0;
3056 : 119 : def_val_len = 0;
3057 : : }
3058 [ - + ]: 228 : else if( MB_SUCCESS != rval )
3059 : : {
3060 [ # # ]: 0 : H5Tclose( hdf_type );
3061 : 0 : return error( rval );
3062 : : }
3063 : :
3064 : : // Get mesh value
3065 : : unsigned char byte;
3066 : 347 : const EntityHandle root = 0;
3067 [ - + ]: 347 : if( mb_storage == MB_TAG_BIT )
3068 : : {
3069 [ # # ]: 0 : rval = iFace->tag_get_data( tag_data.tag_id, &root, 1, &byte );
3070 : 0 : mesh_value = &byte;
3071 : 0 : mesh_val_len = 1;
3072 : : }
3073 : : else
3074 : : {
3075 [ + - ]: 347 : rval = iFace->tag_get_by_ptr( tag_data.tag_id, &root, 1, &mesh_value, &mesh_val_len );
3076 : : }
3077 [ + + ]: 347 : if( MB_TAG_NOT_FOUND == rval )
3078 : : {
3079 : 119 : mesh_value = 0;
3080 : 119 : mesh_val_len = 0;
3081 : : }
3082 [ - + ]: 228 : else if( MB_SUCCESS != rval )
3083 : : {
3084 [ # # ]: 0 : H5Tclose( hdf_type );
3085 : 0 : return error( rval );
3086 : : }
3087 : :
3088 : : // For handle-type tags, need to convert from handles to file ids
3089 [ + + ]: 347 : if( MB_TYPE_HANDLE == mb_type )
3090 : : {
3091 : : // Make sure there's room in the buffer for both
3092 [ - + ]: 47 : assert( ( def_val_len + mesh_val_len ) * sizeof( long ) < (size_t)bufferSize );
3093 : :
3094 : : // Convert default value
3095 [ + + ]: 47 : if( def_value )
3096 : : {
3097 : 8 : memcpy( dataBuffer, def_value, def_val_len * sizeof( EntityHandle ) );
3098 [ + - ]: 8 : convert_handle_tag( reinterpret_cast< EntityHandle* >( dataBuffer ), def_val_len );
3099 : 8 : def_value = dataBuffer;
3100 : : }
3101 : :
3102 : : // Convert mesh value
3103 [ + + ]: 47 : if( mesh_value )
3104 : : {
3105 : 8 : EntityHandle* ptr = reinterpret_cast< EntityHandle* >( dataBuffer ) + def_val_len;
3106 : 8 : memcpy( ptr, mesh_value, mesh_val_len * sizeof( EntityHandle ) );
3107 [ + - ][ - + ]: 8 : if( convert_handle_tag( ptr, mesh_val_len ) )
3108 : 0 : mesh_value = ptr;
3109 : : else
3110 : 47 : mesh_value = 0;
3111 : : }
3112 : : }
3113 : :
3114 [ + + ]: 347 : if( MB_VARIABLE_LENGTH != tag_bytes )
3115 : : {
3116 : : // Write the tag description to the file
3117 : : mhdf_createTag( filePtr, tag_name.c_str(), mhdf_type, num_vals, storage, def_value, mesh_value, hdf_type,
3118 [ + + ][ + - ]: 323 : mb_type == MB_TYPE_HANDLE ? id_type : 0, &status );
3119 [ + - ][ - + ]: 323 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
3120 [ + - ]: 323 : H5Tclose( hdf_type );
3121 : :
3122 : : // Create empty table for tag data
3123 [ + + ]: 323 : if( num_sparse_entities )
3124 : : {
3125 [ + - ]: 95 : mhdf_createSparseTagData( filePtr, tag_name.c_str(), num_sparse_entities, handles, &status );
3126 [ + - ][ - + ]: 95 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
3127 [ + - ]: 95 : mhdf_closeData( filePtr, handles[0], &status );
3128 [ + - ]: 95 : mhdf_closeData( filePtr, handles[1], &status );
3129 : : }
3130 : :
3131 [ + + ]: 429 : for( size_t i = 0; i < tag_data.dense_list.size(); ++i )
3132 : : {
3133 [ + - ][ + - ]: 106 : const ExportSet* ex = find( tag_data.dense_list[i] );
3134 [ - + ]: 106 : assert( 0 != ex );
3135 [ + - ][ + - ]: 106 : handles[0] = mhdf_createDenseTagData( filePtr, tag_name.c_str(), ex->name(), ex->total_num_ents, &status );
3136 [ + - ][ - + ]: 106 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
3137 [ + - ]: 106 : mhdf_closeData( filePtr, handles[0], &status );
3138 : : }
3139 : : }
3140 : : else
3141 : : {
3142 : : mhdf_createVarLenTag( filePtr, tag_name.c_str(), mhdf_type, storage, def_value, def_val_len, mesh_value,
3143 [ + + ][ + - ]: 24 : mesh_val_len, hdf_type, mb_type == MB_TYPE_HANDLE ? id_type : 0, &status );
3144 [ + - ][ - + ]: 24 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
3145 [ + - ]: 24 : H5Tclose( hdf_type );
3146 : :
3147 : : // Create empty table for tag data
3148 [ + + ]: 24 : if( num_sparse_entities )
3149 : : {
3150 : : mhdf_createVarLenTagData( filePtr, tag_name.c_str(), num_sparse_entities, data_table_size, handles,
3151 [ + - ]: 23 : &status );
3152 [ + - ][ - + ]: 23 : CHK_MHDF_ERR_0( status );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
3153 [ + - ]: 23 : mhdf_closeData( filePtr, handles[0], &status );
3154 [ + - ]: 23 : mhdf_closeData( filePtr, handles[1], &status );
3155 [ + - ]: 23 : mhdf_closeData( filePtr, handles[2], &status );
3156 : : }
3157 : : }
3158 : :
3159 : 694 : return MB_SUCCESS;
3160 : : }
3161 : :
3162 : 0 : ErrorCode WriteHDF5::get_num_sparse_tagged_entities( const TagDesc& tag, size_t& count )
3163 : : {
3164 [ # # ]: 0 : Range tmp;
3165 [ # # ]: 0 : ErrorCode rval = get_sparse_tagged_entities( tag, tmp );
3166 [ # # ]: 0 : count = tmp.size();
3167 : 0 : return rval;
3168 : : }
3169 : :
3170 : 465 : ErrorCode WriteHDF5::get_sparse_tagged_entities( const TagDesc& tag, Range& results )
3171 : : {
3172 [ + - ]: 465 : results.clear();
3173 [ + - ][ + - ]: 465 : if( !tag.have_dense( setSet ) ) results.merge( setSet.range );
[ + - ]
3174 [ + - ]: 465 : std::list< ExportSet >::reverse_iterator e;
3175 [ + - ][ + - ]: 1182 : for( e = exportList.rbegin(); e != exportList.rend(); ++e )
[ + + ]
3176 : : {
3177 [ + - ][ + - ]: 717 : if( !tag.have_dense( *e ) ) results.merge( e->range );
[ + - ][ + - ]
[ + - ]
3178 : : }
3179 [ + - ][ + - ]: 465 : if( !tag.have_dense( nodeSet ) ) results.merge( nodeSet.range );
[ + - ]
3180 [ + - ][ - + ]: 465 : if( results.empty() ) return MB_SUCCESS;
3181 : :
3182 [ + - ]: 465 : return iFace->get_entities_by_type_and_tag( 0, MBMAXTYPE, &tag.tag_id, 0, 1, results, Interface::INTERSECT );
3183 : : }
3184 : :
3185 : 0 : void WriteHDF5::get_write_entities( Range& range )
3186 : : {
3187 [ # # ]: 0 : range.clear();
3188 [ # # ]: 0 : range.merge( setSet.range );
3189 [ # # ]: 0 : std::list< ExportSet >::reverse_iterator e;
3190 [ # # ][ # # ]: 0 : for( e = exportList.rbegin(); e != exportList.rend(); ++e )
[ # # ]
3191 [ # # ][ # # ]: 0 : range.merge( e->range );
3192 [ # # ]: 0 : range.merge( nodeSet.range );
3193 : 0 : }
3194 : :
3195 : 0 : void WriteHDF5::print_id_map() const
3196 : : {
3197 : 0 : print_id_map( std::cout, "" );
3198 : 0 : }
3199 : :
3200 : 0 : void WriteHDF5::print_id_map( std::ostream& s, const char* pfx ) const
3201 : : {
3202 : 0 : RangeMap< EntityHandle, wid_t >::const_iterator i;
3203 [ # # ][ # # ]: 0 : for( i = idMap.begin(); i != idMap.end(); ++i )
[ # # ][ # # ]
[ # # ]
3204 : : {
3205 [ # # ][ # # ]: 0 : const char* n1 = CN::EntityTypeName( TYPE_FROM_HANDLE( i->begin ) );
[ # # ]
3206 [ # # ][ # # ]: 0 : EntityID id = ID_FROM_HANDLE( i->begin );
3207 [ # # ][ # # ]: 0 : if( 1 == i->count ) { s << pfx << n1 << " " << id << " -> " << i->value << std::endl; }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
3208 : : else
3209 : : {
3210 [ # # ][ # # ]: 0 : const char* n2 = CN::EntityTypeName( TYPE_FROM_HANDLE( i->begin + i->count - 1 ) );
[ # # ][ # # ]
3211 [ # # ]: 0 : if( n1 == n2 )
3212 : : {
3213 [ # # ][ # # ]: 0 : s << pfx << n1 << " " << id << "-" << id + i->count - 1 << " -> " << i->value << "-"
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
3214 [ # # ][ # # ]: 0 : << i->value + i->count - 1 << std::endl;
[ # # ][ # # ]
3215 : : }
3216 : : else
3217 : : {
3218 [ # # ][ # # ]: 0 : s << pfx << n1 << " " << id << "-" << n1 << " " << ID_FROM_HANDLE( i->begin + i->count - 1 ) << " -> "
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
3219 [ # # ][ # # ]: 0 : << i->value << "-" << i->value + i->count - 1 << std::endl;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
3220 : : }
3221 : : }
3222 : : }
3223 : 0 : }
3224 : :
3225 : 0 : void WriteHDF5::print_times( const double* t ) const
3226 : : {
3227 : 0 : std::cout << "WriteHDF5: " << t[TOTAL_TIME] << std::endl
3228 : 0 : << " gather mesh: " << t[GATHER_TIME] << std::endl
3229 : 0 : << " create file: " << t[CREATE_TIME] << std::endl
3230 : 0 : << " create nodes: " << t[CREATE_NODE_TIME] << std::endl
3231 : 0 : << " negotiate types: " << t[NEGOTIATE_TYPES_TIME] << std::endl
3232 : 0 : << " create elem: " << t[CREATE_ELEM_TIME] << std::endl
3233 : 0 : << " file id exch: " << t[FILEID_EXCHANGE_TIME] << std::endl
3234 : 0 : << " create adj: " << t[CREATE_ADJ_TIME] << std::endl
3235 : 0 : << " create set: " << t[CREATE_SET_TIME] << std::endl
3236 : 0 : << " shared ids: " << t[SHARED_SET_IDS] << std::endl
3237 : 0 : << " shared data: " << t[SHARED_SET_CONTENTS] << std::endl
3238 : 0 : << " set offsets: " << t[SET_OFFSET_TIME] << std::endl
3239 : 0 : << " create tags: " << t[CREATE_TAG_TIME] << std::endl
3240 : 0 : << " coordinates: " << t[COORD_TIME] << std::endl
3241 : 0 : << " connectivity: " << t[CONN_TIME] << std::endl
3242 : 0 : << " sets: " << t[SET_TIME] << std::endl
3243 : 0 : << " set descrip: " << t[SET_META] << std::endl
3244 : 0 : << " set content: " << t[SET_CONTENT] << std::endl
3245 : 0 : << " set parent: " << t[SET_PARENT] << std::endl
3246 : 0 : << " set child: " << t[SET_CHILD] << std::endl
3247 : 0 : << " adjacencies: " << t[ADJ_TIME] << std::endl
3248 : 0 : << " tags: " << t[TAG_TIME] << std::endl
3249 : 0 : << " dense data: " << t[DENSE_TAG_TIME] << std::endl
3250 : 0 : << " sparse data: " << t[SPARSE_TAG_TIME] << std::endl
3251 : 0 : << " var-len data: " << t[VARLEN_TAG_TIME] << std::endl;
3252 : 0 : }
3253 : :
3254 [ + - ][ + - ]: 228 : } // namespace moab
|