LCOV - code coverage report
Current view: top level - src/io - WriteHDF5.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 1273 1561 81.6 %
Date: 2020-12-16 07:07:30 Functions: 59 69 85.5 %
Branches: 1499 4386 34.2 %

           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, &copy_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

Generated by: LCOV version 1.11