[MOAB-dev] r1589 - MOAB/trunk
kraftche at mcs.anl.gov
kraftche at mcs.anl.gov
Tue Feb 5 19:01:32 CST 2008
Author: kraftche
Date: 2008-02-05 19:01:31 -0600 (Tue, 05 Feb 2008)
New Revision: 1589
Modified:
MOAB/trunk/ReadHDF5.cpp
MOAB/trunk/ReadHDF5.hpp
MOAB/trunk/WriteHDF5.cpp
MOAB/trunk/WriteHDF5.hpp
Log:
Serial I/O for variable-length tags.
Modified: MOAB/trunk/ReadHDF5.cpp
===================================================================
--- MOAB/trunk/ReadHDF5.cpp 2008-02-06 01:00:42 UTC (rev 1588)
+++ MOAB/trunk/ReadHDF5.cpp 2008-02-06 01:01:31 UTC (rev 1589)
@@ -1088,7 +1088,7 @@
int have_sparse; // File contains sparse data table for tag
hid_t hdf_type = 0; // Type to use when reading tag data.
int elem_size; // Bytes required for one elem of array
- hsize_t array_size; // If tag is not opaque, the number of data per entity
+ int array_size; // If tag is not opaque, the number of data per entity
MBTag handle; // The handle for the tag
MBDataType mb_type; // The MOAB data type for the data
@@ -1158,8 +1158,14 @@
case mhdf_OPAQUE:
default:
- elem_size = tag_size;
- array_size = 1;
+ if (tag_size < 0) { // variable-length
+ elem_size = 1;
+ array_size = -1;
+ }
+ else {
+ elem_size = tag_size;
+ array_size = 1;
+ }
mb_type = MB_TYPE_OPAQUE;
hdf_type = (hid_t)0;
@@ -1181,22 +1187,38 @@
break;
}
+ if (tag_size < 0) // variable length
+ tag_size = MB_VARIABLE_LENGTH;
// Create array type from base type if array
if (array_size > 1)
{
- hdf_type = H5Tarray_create( hdf_type, 1, &array_size, NULL );
+ hsize_t tmpsize = array_size;
+ hdf_type = H5Tarray_create( hdf_type, 1, &tmpsize, NULL );
if (hdf_type < 0)
return MB_FAILURE;
}
// If default or global/mesh value in file, read it.
+ void *default_ptr = 0, *global_ptr = 0;
+ int default_size = 0, global_size = 0;
if (have_default || have_global)
{
- assert( 3*tag_size < bufferSize );
- mhdf_getTagValues( filePtr, name, hdf_type, dataBuffer, dataBuffer + tag_size, &status );
+ if (array_size == -1) { // variable-length tag
+ default_size = have_default;
+ global_size = have_global;
+ }
+ else {
+ default_size = global_size = array_size;
+ }
+
+ assert( (default_size + global_size) * elem_size <= bufferSize );
+ default_ptr = dataBuffer;
+ global_ptr = dataBuffer + default_size*elem_size;
+
+ mhdf_getTagValues( filePtr, name, hdf_type, default_ptr, global_ptr, &status );
if (mhdf_isError( &status ))
{
readUtil->report_error( mhdf_message( &status ) );
@@ -1205,17 +1227,19 @@
if (MB_TYPE_HANDLE == mb_type) {
if (have_default) {
- rval = convert_id_to_handle( (MBEntityHandle*)dataBuffer, array_size );
+ rval = convert_id_to_handle( (MBEntityHandle*)default_ptr, default_size );
if (MB_SUCCESS != rval)
have_default = 0;
}
if (have_global) {
- rval = convert_id_to_handle( (MBEntityHandle*)(dataBuffer+tag_size), array_size );
+ rval = convert_id_to_handle( (MBEntityHandle*)global_ptr, global_size );
if (MB_SUCCESS != rval)
have_global = 0;
}
}
}
+ global_size *= elem_size;
+ default_size *= elem_size;
// Check if tag already exists
@@ -1228,7 +1252,9 @@
MBTagType curr_store;
rval = iFace->tag_get_size( handle, curr_size );
- if (MB_SUCCESS != rval)
+ if (MB_VARIABLE_DATA_LENGTH == rval)
+ curr_size = -1;
+ else if (MB_SUCCESS != rval)
return rval;
rval = iFace->tag_get_data_type( handle, curr_type );
@@ -1251,8 +1277,12 @@
// Create the tag if it doesn't exist
else if (MB_TAG_NOT_FOUND == rval)
{
- rval = iFace->tag_create( name, tag_size, (MBTagType)storage, mb_type,
- handle, have_default ? dataBuffer : 0 );
+ if (tag_size == MB_VARIABLE_LENGTH)
+ rval = iFace->tag_create_variable_length( name, (MBTagType)storage, mb_type,
+ handle, default_ptr, default_size );
+ else
+ rval = iFace->tag_create( name, tag_size, (MBTagType)storage, mb_type,
+ handle, default_ptr );
if (MB_SUCCESS != rval)
return rval;
}
@@ -1261,15 +1291,19 @@
return rval;
if (have_global) {
- rval = iFace->tag_set_data( handle, 0, 0, dataBuffer + tag_size );
+ rval = iFace->tag_set_data( handle, 0, 0, &global_ptr, &global_size );
if (MB_SUCCESS != rval)
return rval;
}
// Read tag data
MBErrorCode tmp = MB_SUCCESS;
- if (have_sparse)
- tmp = read_sparse_tag( handle, hdf_type, tag_size, mb_type == MB_TYPE_HANDLE );
+ if (have_sparse) {
+ if (tag_size == MB_VARIABLE_LENGTH)
+ tmp = read_var_len_tag( handle, hdf_type, mb_type == MB_TYPE_HANDLE );
+ else
+ tmp = read_sparse_tag( handle, hdf_type, tag_size, mb_type == MB_TYPE_HANDLE );
+ }
rval = read_dense_tag( handle, hdf_type, tag_size, mb_type == MB_TYPE_HANDLE );
@@ -1442,7 +1476,7 @@
std::string name;
MBErrorCode rval;
long num_values;
- hid_t data[2];
+ hid_t data[3];
MBTagType mbtype;
assert ((hdf_read_type == 0) || (H5Tget_size(hdf_read_type) == read_size));
@@ -1555,6 +1589,122 @@
return MB_SUCCESS;
}
+MBErrorCode ReadHDF5::read_var_len_tag( MBTag tag_handle,
+ hid_t hdf_read_type,
+ bool is_handle_type )
+{
+ mhdf_Status status;
+ std::string name;
+ MBErrorCode rval;
+ long num_values;
+ hid_t data[3];
+ MBTagType mbtype;
+ // hdf_read_type is NULL (zero) for opaque tag data.
+ long elem_size = hdf_read_type ? H5Tget_size( hdf_read_type ) : 1;
+ if (elem_size < 1) // invalid type handle?
+ return MB_FAILURE;
+
+ rval = iFace->tag_get_name( tag_handle, name );
+ if (MB_SUCCESS != rval)
+ return rval;
+
+ rval = iFace->tag_get_type( tag_handle, mbtype );
+ if (MB_SUCCESS != rval)
+ return rval;
+
+ mhdf_openSparseTagData( filePtr, name.c_str(), &num_values, data, &status );
+ if (mhdf_isError( &status ) )
+ {
+ readUtil->report_error( mhdf_message( &status ) );
+ return MB_FAILURE;
+ }
+
+ // Process each entity individually
+ MBEntityHandle id;
+ long offset, prev_offset = 0;
+ for (long i = 0; i < num_values; ++i) {
+ // read entity ID
+ mhdf_readSparseTagEntities( data[0], i, 1, handleType, &id, &status );
+ if (mhdf_isError( &status ))
+ {
+ readUtil->report_error( mhdf_message( &status ) );
+ mhdf_closeData( filePtr, data[0], &status );
+ mhdf_closeData( filePtr, data[1], &status );
+ mhdf_closeData( filePtr, data[2], &status );
+ return MB_FAILURE;
+ }
+ // convert entity ID to MBEntityHandle
+ rval = convert_id_to_handle( &id, 1 );
+ if (MB_SUCCESS != rval)
+ {
+ mhdf_closeData( filePtr, data[0], &status );
+ mhdf_closeData( filePtr, data[1], &status );
+ mhdf_closeData( filePtr, data[2], &status );
+ return rval;
+ }
+ // read end index of tag value
+ mhdf_readSparseTagIndices( data[2], i, 1, H5T_NATIVE_LONG, &offset, &status );
+ if (mhdf_isError( &status ))
+ {
+ readUtil->report_error( mhdf_message( &status ) );
+ mhdf_closeData( filePtr, data[0], &status );
+ mhdf_closeData( filePtr, data[1], &status );
+ mhdf_closeData( filePtr, data[2], &status );
+ return MB_FAILURE;
+ }
+ // calculate length of tag value
+ ++offset;
+ int count = (int)(offset - prev_offset);
+ assert( count * elem_size <= bufferSize );
+ mhdf_readSparseTagValues( data[1], prev_offset, count, hdf_read_type, dataBuffer, &status );
+ if (mhdf_isError( &status ))
+ {
+ readUtil->report_error( mhdf_message( &status ) );
+ mhdf_closeData( filePtr, data[0], &status );
+ mhdf_closeData( filePtr, data[1], &status );
+ mhdf_closeData( filePtr, data[2], &status );
+ return MB_FAILURE;
+ }
+ // for handle-type tags, convert file IDs to MBEntityHandles in tag data
+ if (is_handle_type)
+ {
+ rval = convert_id_to_handle( (MBEntityHandle*)dataBuffer, count );
+ if (MB_SUCCESS != rval)
+ {
+ mhdf_closeData( filePtr, data[0], &status );
+ mhdf_closeData( filePtr, data[1], &status );
+ mhdf_closeData( filePtr, data[2], &status );
+ return rval;
+ }
+ }
+ // set tag data
+ const void* ptrarr[1] = { dataBuffer };
+ int bytes = count * elem_size;
+ rval = iFace->tag_set_data( tag_handle, &id, 1, ptrarr, &bytes );
+ if (MB_SUCCESS != rval)
+ {
+ mhdf_closeData( filePtr, data[0], &status );
+ mhdf_closeData( filePtr, data[1], &status );
+ mhdf_closeData( filePtr, data[2], &status );
+ return rval;
+ }
+ // iterate
+ prev_offset = offset;
+ }
+
+ mhdf_closeData( filePtr, data[0], &status );
+ if (mhdf_isError( &status ) )
+ readUtil->report_error( mhdf_message( &status ) );
+ mhdf_closeData( filePtr, data[1], &status );
+ if (mhdf_isError( &status ) )
+ readUtil->report_error( mhdf_message( &status ) );
+ mhdf_closeData( filePtr, data[2], &status );
+ if (mhdf_isError( &status ) )
+ readUtil->report_error( mhdf_message( &status ) );
+
+ return MB_SUCCESS;
+}
+
MBErrorCode ReadHDF5::convert_id_to_handle( const ElemSet& elems,
MBEntityHandle* array,
size_t size )
Modified: MOAB/trunk/ReadHDF5.hpp
===================================================================
--- MOAB/trunk/ReadHDF5.hpp 2008-02-06 01:00:42 UTC (rev 1588)
+++ MOAB/trunk/ReadHDF5.hpp 2008-02-06 01:01:31 UTC (rev 1589)
@@ -139,6 +139,11 @@
hid_t hdf_read_type,
size_t read_size,
bool is_handle_type );
+
+ //! Read variable-length tag for all entities.
+ MBErrorCode read_var_len_tag( MBTag tag_handle,
+ hid_t hdf_read_type,
+ bool is_handle_type );
MBErrorCode read_qa( MBEntityHandle& import_set_out );
Modified: MOAB/trunk/WriteHDF5.cpp
===================================================================
--- MOAB/trunk/WriteHDF5.cpp 2008-02-06 01:00:42 UTC (rev 1588)
+++ MOAB/trunk/WriteHDF5.cpp 2008-02-06 01:01:31 UTC (rev 1589)
@@ -117,6 +117,16 @@
return MB_FAILURE; \
} while(false)
+#define CHK_MHDF_ERR_3( A, B ) \
+do if ( mhdf_isError( &(A) )) { \
+ writeUtil->report_error( "%s\n", mhdf_message( &(A) ) );\
+ myassert(0); \
+ mhdf_closeData( filePtr, (B)[0], &(A) ); \
+ mhdf_closeData( filePtr, (B)[1], &(A) ); \
+ mhdf_closeData( filePtr, (B)[2], &(A) ); \
+ return MB_FAILURE; \
+} while(false)
+
#define CHK_MHDF_ERR_2C( A, B, C, D ) \
do if ( mhdf_isError( &(A) )) { \
writeUtil->report_error( "%s\n", mhdf_message( &(A) ) );\
@@ -146,6 +156,16 @@
return (A); \
} while(false)
+#define CHK_MB_ERR_3( A, B, C ) \
+do if (MB_SUCCESS != (A)) { \
+ mhdf_closeData( filePtr, (B)[0], &(C) ); \
+ mhdf_closeData( filePtr, (B)[1], &(C) ); \
+ mhdf_closeData( filePtr, (B)[2], &(C) ); \
+ write_finished(); \
+ myassert(0); \
+ return (A); \
+} while(false)
+
#define CHK_MB_ERR_2C( A, B, C, D, E ) \
do if (MB_SUCCESS != (A)) { \
mhdf_closeData( filePtr, (B), &(E) ); \
@@ -430,10 +450,16 @@
// Write tags
for (t_itor = tagList.begin(); t_itor != tagList.end(); ++t_itor)
- if (t_itor->write)
- if (write_sparse_tag( *t_itor ) != MB_SUCCESS)
+ if (t_itor->write) {
+ int size;
+ if (MB_VARIABLE_DATA_LENGTH == iFace->tag_get_size( t_itor->tag_id, size ))
+ result = write_var_len_tag( *t_itor );
+ else
+ result = write_sparse_tag( *t_itor );
+ if (MB_SUCCESS != result)
goto write_fail;
-
+ }
+
DEBUGOUT("Closing file.\n");
// Clean up and exit.
@@ -1378,36 +1404,12 @@
*/
-MBErrorCode WriteHDF5::write_sparse_tag( const SparseTag& tag_data )
+MBErrorCode WriteHDF5::write_sparse_ids( const SparseTag& tag_data,
+ hid_t id_table )
{
MBErrorCode rval;
mhdf_Status status;
- hid_t tables[2];
- std::string name;
- int mb_size;
- MBTagType mb_type;
- MBDataType mb_data_type;
- long table_size;
-
- //get tag properties from moab
- if (MB_SUCCESS != iFace->tag_get_name( tag_data.tag_id, name ) ||
- MB_SUCCESS != iFace->tag_get_type( tag_data.tag_id, mb_type ) ||
- MB_SUCCESS != iFace->tag_get_size( tag_data.tag_id, mb_size ) ||
- MB_SUCCESS != iFace->tag_get_data_type( tag_data.tag_id, mb_data_type ))
- return MB_FAILURE;
- if (mb_type == MB_TAG_BIT)
- mb_size = 1;
-DEBUGOUT((std::string("Tag: ") + name + "\n").c_str());
-
- //open tables to write info
- mhdf_openSparseTagData( filePtr,
- name.c_str(),
- &table_size,
- tables,
- &status);
- CHK_MHDF_ERR_0(status);
- assert( tag_data.range.size() + tag_data.offset <= (unsigned long)table_size );
// Set up data buffer for writing IDs
size_t chunk_size = bufferSize / sizeof(id_t);
@@ -1431,27 +1433,67 @@
assert(range.size() == (unsigned)count);
rval = iFace->tag_get_data( idTag, range, id_buffer );
- CHK_MB_ERR_2( rval, tables, status );
+ CHK_MB_ERR_0( rval );
// write the data
- mhdf_writeSparseTagEntities( tables[0], offset, count, id_type,
+ mhdf_writeSparseTagEntities( id_table, offset, count, id_type,
id_buffer, &status );
- CHK_MHDF_ERR_2( status, tables );
+ CHK_MHDF_ERR_0( status );
offset += count;
} // while (remaining)
+
+ return MB_SUCCESS;
+}
+
+MBErrorCode WriteHDF5::write_sparse_tag( const SparseTag& tag_data )
+{
+ MBErrorCode rval;
+ mhdf_Status status;
+ hid_t tables[3];
+ std::string name;
+ int mb_size;
+ MBTagType mb_type;
+ MBDataType mb_data_type;
+ long table_size;
+
+ //get tag properties from moab
+ if (MB_SUCCESS != iFace->tag_get_name( tag_data.tag_id, name ) ||
+ MB_SUCCESS != iFace->tag_get_type( tag_data.tag_id, mb_type ) ||
+ MB_SUCCESS != iFace->tag_get_size( tag_data.tag_id, mb_size ) ||
+ MB_SUCCESS != iFace->tag_get_data_type( tag_data.tag_id, mb_data_type ))
+ return MB_FAILURE;
+ if (mb_size <= 0)
+ return MB_FAILURE;
+ if (mb_type == MB_TAG_BIT)
+ mb_size = 1;
+
+DEBUGOUT((std::string("Tag: ") + name + "\n").c_str());
+
+ //open tables to write info
+ mhdf_openSparseTagData( filePtr,
+ name.c_str(),
+ &table_size,
+ tables,
+ &status);
+ CHK_MHDF_ERR_0(status);
+ assert( tag_data.range.size() + tag_data.offset <= (unsigned long)table_size );
+
+ // Write IDs for tagged entities
+ rval = write_sparse_ids( tag_data, tables[0] );
+ CHK_MB_ERR_2( rval, tables, status );
mhdf_closeData( filePtr, tables[0], &status );
- CHK_MHDF_ERR_0(status);
+ CHK_MHDF_ERR_1(status, tables[1]);
// Set up data buffer for writing tag values
- chunk_size = bufferSize / mb_size;
+ size_t chunk_size = bufferSize / mb_size;
assert( chunk_size > 0 );
char* tag_buffer = (char*)dataBuffer;
// Write the tag values
- remaining = tag_data.range.size();
- offset = tag_data.offset;
- iter = tag_data.range.begin();
+ size_t remaining = tag_data.range.size();
+ size_t offset = tag_data.offset;
+ MBRange::const_iterator iter = tag_data.range.begin();
while (remaining)
{
// write "chunk_size" blocks of data
@@ -1460,7 +1502,7 @@
memset( tag_buffer, 0, count * mb_size );
MBRange::const_iterator stop = iter;
stop += count;
- range.clear();
+ MBRange range;
range.merge( iter, stop );
iter = stop;
assert(range.size() == (unsigned)count);
@@ -1499,6 +1541,91 @@
return MB_SUCCESS;
}
+MBErrorCode WriteHDF5::write_var_len_tag( const SparseTag& tag_data )
+{
+ MBErrorCode rval;
+ mhdf_Status status;
+ hid_t tables[3];
+ std::string name;
+ long table_size;
+
+ //get tag properties from moab
+ if (MB_SUCCESS != iFace->tag_get_name( tag_data.tag_id, name ))
+ return MB_FAILURE;
+
+ // get type and size information
+ int mb_size, type_size, file_size;
+ MBDataType mb_data_type;
+ mhdf_TagDataType file_type;
+ hid_t hdf_type;
+ if (MB_SUCCESS != get_tag_size( tag_data.tag_id,
+ mb_data_type,
+ mb_size,
+ type_size,
+ file_size,
+ file_type,
+ hdf_type ))
+ return MB_FAILURE;
+
+ if (mb_data_type == MB_TYPE_BIT) //can't do variable-length bit tags
+ return MB_FAILURE;
+ if (mb_size != MB_VARIABLE_LENGTH)
+ return MB_FAILURE;
+
+DEBUGOUT((std::string("Tag: ") + name + "\n").c_str());
+
+ //open tables to write info
+ mhdf_openSparseTagData( filePtr,
+ name.c_str(),
+ &table_size,
+ tables,
+ &status);
+ CHK_MHDF_ERR_0(status);
+ assert( tag_data.range.size() + tag_data.offset <= (unsigned long)table_size );
+
+ // Write IDs for tagged entities
+ rval = write_sparse_ids( tag_data, tables[0] );
+ CHK_MB_ERR_2( rval, tables, status );
+ mhdf_closeData( filePtr, tables[0], &status );
+ CHK_MHDF_ERR_2(status, tables + 1);
+
+ // Write each tag value separately
+ size_t indx_offset = tag_data.offset;
+ size_t data_offset = tag_data.varDataOffset;
+ int size;
+ unsigned long idx;
+ const void* ptr;
+ for (MBRange::const_iterator i = tag_data.range.begin();
+ i!= tag_data.range.end(); ++i, ++indx_offset) {
+
+ rval = iFace->tag_get_data( tag_data.tag_id, &*i, 1, &ptr, &size );
+ CHK_MB_ERR_2(rval, tables + 1, status);
+
+ // Convert MBEntityHandles to file ids
+ if (mb_data_type == MB_TYPE_HANDLE) {
+ assert( size < bufferSize );
+ memcpy( dataBuffer, ptr, size );
+ convert_handle_tag( iFace, idTag, dataBuffer, size / sizeof(MBEntityHandle) );
+ ptr = dataBuffer;
+ }
+
+ mhdf_writeSparseTagValues( tables[1], data_offset, size/type_size, hdf_type, ptr, &status );
+ CHK_MHDF_ERR_2(status, tables + 1);
+
+ idx = data_offset + size/type_size - 1;
+ mhdf_writeSparseTagIndices( tables[2], indx_offset, 1, H5T_NATIVE_ULONG, &idx, &status );
+ CHK_MHDF_ERR_2(status, tables + 1);
+ data_offset += size/type_size;
+ }
+
+ mhdf_closeData( filePtr, tables[1], &status );
+ CHK_MHDF_ERR_1(status, tables[2]);
+ mhdf_closeData( filePtr, tables[2], &status );
+ CHK_MHDF_ERR_0(status);
+
+ return MB_SUCCESS;
+}
+
MBErrorCode WriteHDF5::write_qa( std::vector<std::string>& list )
{
const char* app = "MOAB";
@@ -1623,6 +1750,7 @@
SparseTag tag_data;
tag_data.tag_id = *t_itor;
tag_data.offset = 0;
+ tag_data.varDataOffset = 0;
tagList.push_back( tag_data );
}
@@ -1652,7 +1780,12 @@
result = iFace->get_entities_by_type_and_tag( 0, MBENTITYSET, &handle, NULL, 1, range );
CHK_MB_ERR_0(result);
td_iter->range.merge( range.intersect( setSet.range ) );
-
+
+/* This breaks for variable-length tags, is slow, and is questionable.
+ Is it really better to not write the tag at all, as opposed to writing
+ NULL handles? If the tag has a default value, this would result in
+ the tag value changing to the default, which isn't correct.
+
// For tags containing entity handles, skip values if
// handle doesn't reference something being written to the file.
// If the tag contains multiple handle values, write it if any one
@@ -1681,10 +1814,10 @@
i = td_iter->range.erase( i );
}
}
+*/
td_iter->write = !td_iter->range.empty();
}
-
return MB_SUCCESS;
}
@@ -1816,7 +1949,7 @@
const std::list<SparseTag>::iterator tag_end = tagList.end();
for ( ; tag_iter != tag_end; ++tag_iter)
{
- rval = create_tag( tag_iter->tag_id, tag_iter->range.size() );
+ rval = create_tag( *tag_iter );
CHK_MB_ERR_0(rval);
} // for(tags)
@@ -1963,132 +2096,256 @@
return MB_SUCCESS;
}
-MBErrorCode WriteHDF5::create_tag( MBTag tag_id, id_t num_sparse_entities )
+MBErrorCode WriteHDF5::get_tag_size( MBTag tag,
+ MBDataType& moab_type,
+ int& num_bytes,
+ int& elem_size,
+ int& file_size,
+ mhdf_TagDataType& file_type,
+ hid_t& hdf_type )
{
+ MBErrorCode rval;
+ MBTag type_handle;
+ std::string tag_name, tag_type_name;
+
+ // We return NULL for hdf_type if it can be determined from
+ // the file_type. The only case where it is non-zero is
+ // if the user specified a specific type via a mesh tag.
+ hdf_type = (hid_t)0;
+
+ rval = iFace->tag_get_data_type( tag, moab_type ); CHK_MB_ERR_0(rval);
+ rval = iFace->tag_get_size( tag, num_bytes );
+ if (MB_VARIABLE_DATA_LENGTH == rval)
+ num_bytes = MB_VARIABLE_LENGTH;
+ else if (MB_SUCCESS != rval)
+ return rval;
+
+ switch (moab_type)
+ {
+ case MB_TYPE_INTEGER:
+ elem_size = sizeof(int);
+ file_type = mhdf_INTEGER;
+ break;
+ case MB_TYPE_DOUBLE:
+ elem_size = sizeof(double);
+ file_type = mhdf_FLOAT;
+ break;
+ case MB_TYPE_BIT:
+ elem_size = sizeof(bool);
+ file_type = mhdf_BOOLEAN;
+ break;
+ case MB_TYPE_HANDLE:
+ elem_size = sizeof(MBEntityHandle);
+ file_type = mhdf_ENTITY_ID;
+ break;
+ case MB_TYPE_OPAQUE:
+ default:
+ file_type = mhdf_OPAQUE;
+
+ rval = iFace->tag_get_name( tag, tag_name ); CHK_MB_ERR_0(rval);
+ tag_type_name = "__hdf5_tag_type_";
+ tag_type_name += tag_name;
+ rval = iFace->tag_get_handle( tag_type_name.c_str(), type_handle );
+ if (MB_TAG_NOT_FOUND == rval) {
+ elem_size = 1;
+ }
+ else if (MB_SUCCESS == rval) {
+ int hsize;
+ rval = iFace->tag_get_size( type_handle, hsize );
+ if (hsize != sizeof(hid_t))
+ return MB_FAILURE;
+
+ rval = iFace->tag_get_data( type_handle, 0, 0, &hdf_type );
+ if (rval != MB_SUCCESS)
+ return rval;
+
+ elem_size = H5Tget_size(hdf_type);
+ if (elem_size != num_bytes)
+ return MB_FAILURE;
+ }
+ else {
+ return rval;
+ }
+ }
+
+ if (num_bytes == MB_VARIABLE_LENGTH) {
+ file_size = MB_VARIABLE_LENGTH;
+ }
+ else {
+ if (0 != (num_bytes % elem_size))
+ return MB_FAILURE;
+ file_size = num_bytes / elem_size;
+ }
+
+ return MB_SUCCESS;
+}
+
+MBErrorCode WriteHDF5::get_tag_data_length( const SparseTag& tag_info, unsigned long& result )
+{
+ MBErrorCode rval;
+ result = 0;
+
+ // split buffer into two pieces, one for pointers and one for sizes
+ size_t step, remaining;
+ step = bufferSize / (sizeof(int) + sizeof(void*));
+ const void** ptr_buffer = reinterpret_cast<const void**>(dataBuffer);
+ int* size_buffer = reinterpret_cast<int*>(ptr_buffer + step);
+ MBRange subrange;
+ MBRange::const_iterator iter = tag_info.range.begin();
+ for (remaining = tag_info.range.size(); remaining >= step; remaining -= step) {
+ // get subset of range containing 'count' entities
+ MBRange::const_iterator end = iter; end += step;
+ subrange.clear();
+ subrange.merge( iter, end );
+ iter = end;
+ // get tag sizes for entities
+ rval = iFace->tag_get_data( tag_info.tag_id, subrange, ptr_buffer, size_buffer );
+ if (MB_SUCCESS != rval)
+ return rval;
+ // sum lengths
+ for (size_t i = 0; i < step; ++i)
+ result += size_buffer[i];
+ }
+ // process remaining
+ subrange.clear();
+ subrange.merge( iter, tag_info.range.end() );
+ assert( subrange.size() == remaining );
+ rval = iFace->tag_get_data( tag_info.tag_id, subrange, ptr_buffer, size_buffer );
+ if (MB_SUCCESS != rval)
+ return rval;
+ for (size_t i= 0; i < remaining; ++i)
+ result += size_buffer[i];
+ return MB_SUCCESS;
+}
+
+
+
+MBErrorCode WriteHDF5::create_tag( const SparseTag& tag_info )
+{
+ MBTag tag_id = tag_info.tag_id;
+ unsigned long num_sparse_entities = tag_info.range.size();
MBTagType storage;
MBDataType mb_type;
- MBTag type_handle;
mhdf_TagDataType mhdf_type;
- int tag_size, elem_size = 0, mhdf_size;
+ int tag_size, elem_size, mhdf_size;
hid_t hdf_type = (hid_t)0;
hid_t handles[2];
- std::string tag_name, tag_type_name = "__hdf5_tag_type_";
+ std::string tag_name;
MBErrorCode rval;
mhdf_Status status;
// get tag properties
rval = iFace->tag_get_type( tag_id, storage ); CHK_MB_ERR_0(rval);
- rval = iFace->tag_get_size( tag_id, tag_size ); CHK_MB_ERR_0(rval);
rval = iFace->tag_get_name( tag_id, tag_name ); CHK_MB_ERR_0(rval);
- rval = iFace->tag_get_data_type( tag_id, mb_type ); CHK_MB_ERR_0(rval);
+ rval = get_tag_size( tag_id, mb_type, tag_size, elem_size, mhdf_size, mhdf_type, hdf_type );
+ CHK_MB_ERR_0(rval);
-
- // get type-specific parameters
- if (MB_TAG_BIT == storage)
- {
- mhdf_type = mhdf_BITFIELD;
+ // get default value
+ const void *def_value, *mesh_value;
+ int def_val_len, mesh_val_len;
+ rval = iFace->tag_get_default_value( tag_id, def_value, def_val_len );
+ if (MB_ENTITY_NOT_FOUND == rval) {
+ def_value = 0;
+ def_val_len = 0;
}
- else
- {
- switch (mb_type)
- {
- case MB_TYPE_INTEGER:
- elem_size = sizeof(int);
- mhdf_type = mhdf_INTEGER;
- break;
- case MB_TYPE_DOUBLE:
- elem_size = sizeof(double);
- mhdf_type = mhdf_FLOAT;
- break;
- case MB_TYPE_BIT:
- elem_size = sizeof(bool);
- mhdf_type = mhdf_BOOLEAN;
- break;
- case MB_TYPE_HANDLE:
- elem_size = sizeof(MBEntityHandle);
- mhdf_type = mhdf_ENTITY_ID;
- break;
- case MB_TYPE_OPAQUE:
- default:
- mhdf_type = mhdf_OPAQUE;
-
- tag_type_name = "__hdf5_tag_type_";
- tag_type_name += tag_name;
- rval = iFace->tag_get_handle( tag_type_name.c_str(), type_handle );
- if (MB_SUCCESS == rval)
- {
- rval = iFace->tag_get_data( type_handle, 0, 0, &hdf_type );
- if (rval != MB_SUCCESS || H5Tget_size(hdf_type) != (unsigned)tag_size)
- return MB_FAILURE;
- }
- else if(MB_TAG_NOT_FOUND != rval)
- return rval;
- }
- }
+ else if (MB_SUCCESS != rval)
+ return rval;
- // if a basic type, check if it is an array of them
- if (elem_size)
- {
- if (tag_size % elem_size) // tag_size must be a multiple of elem_size
- return MB_FAILURE;
- mhdf_size = tag_size / elem_size;
+ // get mesh value
+ rval = iFace->tag_get_data( tag_id, 0, 0, &mesh_value, &mesh_val_len );
+ if (MB_TAG_NOT_FOUND == rval) {
+ mesh_value = 0;
+ mesh_val_len = 0;
}
- else
- {
- mhdf_size = tag_size;
+ else if (MB_SUCCESS != rval)
+ return rval;
+
+ // for variable-length tags, need to calculate total data table size
+ unsigned long data_table_size = 0;
+ if (tag_size == MB_VARIABLE_LENGTH) {
+ rval = get_tag_data_length( tag_info, data_table_size );
+ CHK_MB_ERR_0(rval);
}
-
- // check for default and global/mesh values
- assert( 2*tag_size + sizeof(long) < (unsigned long)bufferSize );
-
- bool have_default = false;
- rval = iFace->tag_get_default_value( tag_id, dataBuffer );
- if (MB_SUCCESS == rval) {
- have_default = true;
- if (mb_type == MB_TYPE_HANDLE)
- have_default = convert_handle_tag( iFace, idTag, dataBuffer, mhdf_size );
- }
- else if(MB_ENTITY_NOT_FOUND != rval)
- return rval;
+ // for handle-type tags, need to convert from handles to file ids
+ if (MB_TYPE_HANDLE == mb_type) {
+ // make sure there's room in the buffer for both
+ assert( (def_val_len + mesh_val_len) * sizeof(long) < (size_t)bufferSize );
- bool have_global = false;
- rval = iFace->tag_get_data( tag_id, 0, 0, dataBuffer + tag_size );
- if (MB_SUCCESS == rval) {
- have_global = true;
- if (mb_type == MB_TYPE_HANDLE)
- have_default = convert_handle_tag( iFace, idTag, dataBuffer+tag_size, mhdf_size );
+ // convert default value
+ if (def_value) {
+ memcpy( dataBuffer, def_value, def_val_len );
+ if (convert_handle_tag( iFace, idTag, dataBuffer, def_val_len / sizeof(MBEntityHandle) ))
+ def_value = dataBuffer;
+ else
+ def_value = 0;
+ }
+
+ // convert mesh value
+ if (mesh_value) {
+ MBEntityHandle* ptr = reinterpret_cast<MBEntityHandle*>(dataBuffer + def_val_len);
+ memcpy( ptr, mesh_value, mesh_val_len );
+ if (convert_handle_tag( iFace, idTag, ptr, mesh_val_len / sizeof(MBEntityHandle) ))
+ mesh_value = ptr;
+ else
+ mesh_value = 0;
+ }
}
- else if(MB_TAG_NOT_FOUND != rval)
- return rval;
+
+
+ if (MB_VARIABLE_LENGTH != tag_size) {
+ // write the tag description to the file
+ mhdf_createTag( filePtr,
+ tag_name.c_str(),
+ mhdf_type,
+ mhdf_size,
+ storage,
+ def_value,
+ mesh_value,
+ hdf_type,
+ &status );
+ CHK_MHDF_ERR_0(status);
- // write the tag description to the file
- mhdf_createTag( filePtr,
- tag_name.c_str(),
- mhdf_type,
- mhdf_size,
- storage,
- have_default ? dataBuffer : 0,
- have_global ? dataBuffer + tag_size : 0,
- hdf_type,
- &status );
- CHK_MHDF_ERR_0(status);
-
-
- // create empty table for tag data
- if (num_sparse_entities)
- {
- mhdf_createSparseTagData( filePtr,
- tag_name.c_str(),
- num_sparse_entities,
- handles,
- &status );
+ // create empty table for tag data
+ if (num_sparse_entities)
+ {
+ mhdf_createSparseTagData( filePtr,
+ tag_name.c_str(),
+ num_sparse_entities,
+ handles,
+ &status );
+ CHK_MHDF_ERR_0(status);
+ mhdf_closeData( filePtr, handles[0], &status );
+ mhdf_closeData( filePtr, handles[1], &status );
+ }
+ }
+ else {
+ mhdf_createVarLenTag( filePtr,
+ tag_name.c_str(),
+ mhdf_type,
+ storage,
+ def_value, def_val_len / elem_size,
+ mesh_value, mesh_val_len / elem_size,
+ hdf_type,
+ &status );
CHK_MHDF_ERR_0(status);
- mhdf_closeData( filePtr, handles[0], &status );
- mhdf_closeData( filePtr, handles[1], &status );
+
+ // create empty table for tag data
+ if (num_sparse_entities) {
+ mhdf_createVarLenTagData( filePtr,
+ tag_name.c_str(),
+ num_sparse_entities,
+ data_table_size / elem_size,
+ handles,
+ &status );
+ CHK_MHDF_ERR_0(status);
+ mhdf_closeData( filePtr, handles[0], &status );
+ mhdf_closeData( filePtr, handles[1], &status );
+ mhdf_closeData( filePtr, handles[2], &status );
+ }
}
-
+
return MB_SUCCESS;
}
Modified: MOAB/trunk/WriteHDF5.hpp
===================================================================
--- MOAB/trunk/WriteHDF5.hpp 2008-02-06 01:00:42 UTC (rev 1588)
+++ MOAB/trunk/WriteHDF5.hpp 2008-02-06 01:01:31 UTC (rev 1589)
@@ -139,13 +139,6 @@
long children_length,
long parents_length );
- /** Helper function for create-file
- *
- * Write tag meta-info and create zero-ed table where
- * tag values will be written.
- */
- MBErrorCode create_tag( MBTag tag_id, id_t num_sparse_entities );
-
//! Write exodus-type QA info
MBErrorCode write_qa( std::vector<std::string>& list );
@@ -186,8 +179,12 @@
//! The list of entities with this tag
MBRange range;
//! The offset at which to begin writting this processor's data.
- //! Always zero except for parallel IO.
+ //! Always zero except for parallel IO.
id_t offset;
+ //! For variable-length tags, a second offset for the tag data table,
+ //! separate from the offset used for the ID and Index tables.
+ //! Always zero except for parallel IO.
+ id_t varDataOffset;
//! Write tag data (for serial, is always equal to !range.empty())
bool write;
@@ -252,6 +249,13 @@
unsigned long& flags );
protected:
+
+ /** Helper function for create-file
+ *
+ * Write tag meta-info and create zero-ed table where
+ * tag values will be written.
+ */
+ MBErrorCode create_tag( const SparseTag& tag_info );
/** Get possibly compacted list of IDs for passed entities
*
@@ -355,6 +359,38 @@
MBRange::const_iterator end,
int nodes_per_element,
id_t* id_data_out );
+
+ //! get sum of lengths of tag values (in bytes) for
+ //! variable length tag data.
+ MBErrorCode get_tag_data_length( const SparseTag& tag_info,
+ unsigned long& result );
+
+ //! Get size data for tag
+ //!\param tag MOAB tag ID
+ //!\param moab_type Output: MBDataType for tag
+ //!\param num_bytes Output: MOAB tag size (bits for bit tags).
+ //! MB_VARIABLE_LENGTH for variable-length tags.
+ //!\param elem_size Output: Size of type values per entity (e.g.
+ //! sizeof(double) for MB_TYPE_DOUBLE data)
+ //! One for bit and opaque tags.
+ //!\param file_size Output: num_bytes/elem_size
+ //!\param file_type Output: mhdf type enumeration
+ //!\param hdf_type Output: zero or handle for user-defined custom type
+ //! (user-defined type available only for opaque
+ //! data.)
+ MBErrorCode get_tag_size( MBTag tag,
+ MBDataType& moab_type,
+ int& num_bytes,
+ int& elem_size,
+ int& file_size,
+ mhdf_TagDataType& file_type,
+ hid_t& hdf_type );
+
+ //! Write ID table for sparse tag
+ MBErrorCode write_sparse_ids( const SparseTag& tag_data, hid_t table_handle );
+
+ //! Write varialbe-length tag data
+ MBErrorCode write_var_len_tag( const SparseTag& tag_info );
};
#endif
More information about the moab-dev
mailing list