[MOAB-dev] r2088 - MOAB/trunk
dcthomp at mcs.anl.gov
dcthomp at mcs.anl.gov
Wed Sep 24 17:53:15 CDT 2008
Author: dcthomp
Date: 2008-09-24 17:53:14 -0500 (Wed, 24 Sep 2008)
New Revision: 2088
Modified:
MOAB/trunk/ReadVtk.cpp
MOAB/trunk/ReadVtk.hpp
Log:
ENH: Add support for vtkIdType (gets turned into an int)
ENH: Add support for multiple fields per block type (ReadVtk::vtk_read_field_data)
ENH: Add support for partitioning by a field (the PARTITION=xxx option is used to
create one set for each value the field takes on). This is useful for testing.
Modified: MOAB/trunk/ReadVtk.cpp
===================================================================
--- MOAB/trunk/ReadVtk.cpp 2008-09-24 20:40:57 UTC (rev 2087)
+++ MOAB/trunk/ReadVtk.cpp 2008-09-24 22:53:14 UTC (rev 2088)
@@ -27,14 +27,119 @@
#include "MBInternals.hpp"
#include "MBInterface.hpp"
#include "MBReadUtilIface.hpp"
+#include "FileOptions.hpp"
#include "FileTokenizer.hpp"
#include "VtkUtil.hpp"
+#define MB_VTK_MATERIAL_SETS
+#ifdef MB_VTK_MATERIAL_SETS
+# include "MBTagConventions.hpp"
+# include <map>
+
+class MBHash
+{
+public:
+ unsigned long value;
+
+ MBHash()
+ {
+ this->value = 5381L;
+ }
+ MBHash( const unsigned char* bytes, size_t len )
+ { // djb2, a hash by dan bernstein presented on comp.lang.c for hashing strings.
+ this->value = 5381L;
+ for ( ; len ; -- len, ++ bytes )
+ this->value = this->value * 33 + ( *bytes );
+ }
+ MBHash( bool duh )
+ {
+ this->value = duh; // hashing a single bit with a long is stupid but easy.
+ }
+ MBHash( const MBHash& src )
+ {
+ this->value = src.value;
+ }
+ MBHash& operator = ( const MBHash& src )
+ {
+ this->value = src.value;
+ }
+ bool operator < ( const MBHash& other ) const
+ {
+ return this->value < other.value;
+ }
+};
+
+// Pass this class opaque data + a handle and it adds the handle to a set
+// whose opaque data has the same hash. If no set exists for the hash,
+// it creates one. Each set is tagged with the opaque data.
+// When entities with different opaque data have the same hash, they
+// will be placed into the same set.
+// There will be no collisions when the opaque data is shorter than an
+// unsigned long, and this is really the only case we need to support.
+// The rest is bonus. MBHash does quite well with strings, even those
+// with identical prefixes.
+class MBModulator : public std::map<MBHash,MBEntityHandle>
+{
+public:
+ MBModulator( MBInterface* iface, MBEntityHandle fset, std::string tag_name, MBDataType mb_type, size_t size, size_t per_elem )
+ {
+ this->mesh = iface;
+ this->file_set = fset;
+ std::vector<unsigned char> default_val;
+ default_val.resize( size * per_elem );
+ this->mesh->tag_create( tag_name.c_str(), size, MB_TAG_SPARSE,
+ mb_type, this->tag, &default_val[0], true );
+ }
+ void add_entity( MBEntityHandle ent, const unsigned char* bytes, size_t len )
+ {
+ MBHash h( bytes, len );
+ MBEntityHandle mset = this->congruence_class( h, bytes );
+ this->mesh->add_entities( mset, &ent, 1 );
+ }
+ void add_entities( MBRange& range, const unsigned char* bytes, size_t bytes_per_ent )
+ {
+ for( MBRange::iterator it = range.begin(); it != range.end(); ++ it, bytes += bytes_per_ent )
+ {
+ MBHash h( bytes, bytes_per_ent );
+ MBEntityHandle mset = this->congruence_class( h, bytes );
+ this->mesh->add_entities( mset, &*it, 1 );
+ }
+ }
+ MBEntityHandle congruence_class( const MBHash& h, const void* tag_data )
+ {
+ std::map<MBHash,MBEntityHandle>::iterator it = this->find( h );
+ if ( it == this->end() )
+ {
+ MBEntityHandle mset;
+ MBRange preexist;
+ this->mesh->get_entities_by_type_and_tag( 0, MBENTITYSET, &this->tag, &tag_data, 1, preexist );
+ if ( preexist.size() )
+ {
+ mset = *preexist.begin();
+ }
+ else
+ {
+ this->mesh->create_meshset( MESHSET_SET, mset );
+ this->mesh->tag_set_data( this->tag, &mset, 1, tag_data );
+ this->mesh->add_entities( this->file_set, &mset, 1 );
+ }
+ (*this)[h] = mset;
+ return mset;
+ }
+ return it->second;
+ }
+
+ MBInterface* mesh;
+ MBTag tag;
+ MBEntityHandle file_set;
+};
+#endif // MB_VTK_MATERIAL_SETS
+
MBReaderIface* ReadVtk::factory( MBInterface* iface )
{ return new ReadVtk( iface ); }
ReadVtk::ReadVtk(MBInterface* impl)
- : mdbImpl(impl)
+ : mdbImpl(impl), mPartitionTagName(MATERIAL_SET_TAG_NAME)
{
void* ptr = 0;
mdbImpl->query_interface("MBReadUtilIface", &ptr);
@@ -60,12 +165,13 @@
"unsigned_long",
"float",
"double",
+ "vtkIdType",
0 };
MBErrorCode ReadVtk::load_file(const char *filename,
MBEntityHandle& file_set,
- const FileOptions&,
+ const FileOptions& opts,
const int*, const int)
{
MBErrorCode result;
@@ -75,7 +181,14 @@
char vendor_string[257];
std::vector<MBRange> element_list;
MBRange vertices;
-
+
+ // Does the caller want a field to be used for partitioning the entities?
+ // If not, we'll assume any scalar integer field named MATERIAL_SET specifies partitions.
+ std::string partition_tag_name;
+ result = opts.get_option( "PARTITION", partition_tag_name );
+ if ( result == MB_SUCCESS )
+ mPartitionTagName = partition_tag_name;
+
FILE* file = fopen( filename, "r" );
if (!file)
{
@@ -859,9 +972,7 @@
case 4: return vtk_read_vector_attrib ( tokens, entities, name );
case 5: return vtk_read_texture_attrib( tokens, entities, name );
case 6: return vtk_read_tensor_attrib ( tokens, entities, name );
- case 7: // Can't handle field data yet.
- readMeshIface->report_error( "Error at line %d: field data not implemented.\n",
- tokens.line_number() );
+ case 7: return vtk_read_field_attrib ( tokens, entities, name );
default:
return MB_FAILURE;
}
@@ -876,7 +987,6 @@
const char* name )
{
MBErrorCode result;
-
MBDataType mb_type;
size_t size;
if (type == 1)
@@ -894,10 +1004,23 @@
mb_type = MB_TYPE_DOUBLE;
size = sizeof(double);
}
+ else if ( type == 12 )
+ {
+ mb_type = MB_TYPE_INTEGER;
+ size = 4; // could be 4 or 8, but we don't know. Hope it's 4 because MOAB doesn't support 64-bit ints.
+ }
else
{
return MB_FAILURE;
}
+
+#ifdef MB_VTK_MATERIAL_SETS
+ MBModulator materialMap( this->mdbImpl, this->mCurrentMeshHandle, this->mPartitionTagName, mb_type, size, per_elem );
+ bool isMaterial =
+ size * per_elem <= 4 && // must have int-sized values (MBParallelComm requires it)
+ ! this->mPartitionTagName.empty() && // must have a non-empty field name...
+ ! strcmp( name, this->mPartitionTagName.c_str() ); // ... that matches our spec.
+#endif // MB_VTK_MATERIAL_SETS
// get/create tag
MBTag handle;
@@ -962,6 +1085,10 @@
unsigned char bits = 0;
for (unsigned j = 0; j < per_elem; ++j, ++data_iter)
bits |= (unsigned char)(*data_iter << j);
+#ifdef MB_VTK_MATERIAL_SETS
+ if ( isMaterial )
+ materialMap.add_entity( *ent_iter, &bits, 1 );
+#endif // MB_VTK_MATERIAL_SETS
result = mdbImpl->tag_set_data( handle, &*ent_iter, 1, &bits );
if (MB_SUCCESS != result)
{
@@ -972,7 +1099,7 @@
delete [] data;
}
}
- else if (type >= 2 && type <= 9)
+ else if ((type >= 2 && type <= 9) || type == 12)
{
std::vector<int> data;
for (iter = entities.begin(); iter != entities.end(); ++iter)
@@ -980,6 +1107,10 @@
data.resize( iter->size() * per_elem );
if (!tokens.get_integers( iter->size() * per_elem, &data[0] ))
return MB_FAILURE;
+#ifdef MB_VTK_MATERIAL_SETS
+ if ( isMaterial )
+ materialMap.add_entities( *iter, (unsigned char*) &data[0], per_elem * size );
+#endif // MB_VTK_MATERIAL_SETS
result = mdbImpl->tag_set_data( handle, *iter, &data[0] );
if (MB_SUCCESS != result)
return result;
@@ -993,6 +1124,10 @@
data.resize( iter->size() * per_elem );
if (!tokens.get_doubles( iter->size() * per_elem, &data[0] ))
return MB_FAILURE;
+#ifdef MB_VTK_MATERIAL_SETS
+ if ( isMaterial )
+ materialMap.add_entities( *iter, (unsigned char*) &data[0], per_elem * size );
+#endif // MB_VTK_MATERIAL_SETS
result = mdbImpl->tag_set_data( handle, *iter, &data[0] );
if (MB_SUCCESS != result)
return result;
@@ -1006,7 +1141,7 @@
return MB_SUCCESS;
}
-
+
MBErrorCode ReadVtk::vtk_read_scalar_attrib( FileTokenizer& tokens,
std::vector<MBRange>& entities,
const char* name)
@@ -1097,3 +1232,61 @@
return vtk_read_tag_data( tokens, type, 9, entities, name );
}
+MBErrorCode ReadVtk::vtk_read_field_attrib( FileTokenizer& tokens,
+ std::vector<MBRange>& entities,
+ const char* )
+{
+ const char* tok = tokens.get_string( );
+ if (!tok)
+ return MB_FAILURE;
+ long num_fields;
+ const char* end = 0;
+ num_fields = strtol( tok, (char**)&end, 0 );
+ if ( *end )
+ return MB_FAILURE;
+
+ long i;
+ for ( i = 0; i < num_fields; ++ i )
+ {
+ tok = tokens.get_string( );
+ if ( ! tok )
+ return MB_FAILURE;
+
+ std::string name_alloc( tok );
+
+ long num_comp;
+ tok = tokens.get_string( );
+ if ( ! tok )
+ return MB_FAILURE;
+ end = 0;
+ num_comp = strtol( tok, (char**)&end, 0 );
+ if ( *end )
+ return MB_FAILURE;
+
+ long num_tuples;
+ tok = tokens.get_string( );
+ if ( ! tok )
+ return MB_FAILURE;
+ end = 0;
+ num_tuples = strtol( tok, (char**)&end, 0 );
+ if ( *end )
+ return MB_FAILURE;
+
+ int type = tokens.match_token( vtk_type_names );
+ if (!type)
+ return MB_FAILURE;
+
+ MBErrorCode result;
+ if ( ( result = vtk_read_tag_data( tokens, type, num_comp, entities, name_alloc.c_str() ) ) != MB_SUCCESS )
+ {
+ readMeshIface->report_error(
+ "Error reading data for field \"%s\" (%d components, %d tuples, type %d) at line %d",
+ name_alloc.c_str(), num_comp, num_tuples, type, tokens.line_number());
+ return result;
+ }
+ }
+
+ return MB_SUCCESS;
+}
+
+
Modified: MOAB/trunk/ReadVtk.hpp
===================================================================
--- MOAB/trunk/ReadVtk.hpp 2008-09-24 20:40:57 UTC (rev 2087)
+++ MOAB/trunk/ReadVtk.hpp 2008-09-24 22:53:14 UTC (rev 2088)
@@ -19,6 +19,8 @@
#include "MBForward.hpp"
#include "MBReaderIface.hpp"
+#include <string>
+
class MBReadUtilIface;
class FileTokenizer;
@@ -124,6 +126,10 @@
std::vector<MBRange>& entities,
const char* name );
+ MBErrorCode vtk_read_field_attrib( FileTokenizer& tokens,
+ std::vector<MBRange>& entities,
+ const char* name);
+
private:
MBReadUtilIface* readMeshIface;
@@ -135,6 +141,9 @@
//! Meshset Handle for the mesh that is currently being read
MBEntityHandle mCurrentMeshHandle;
+
+ //! A field which, if present and having a single integer for storage, should be used to partition the mesh by range. Defaults to MATERIAL_SET_TAG_NAME
+ std::string mPartitionTagName;
};
#endif
More information about the moab-dev
mailing list