[MOAB-dev] r2864 - MOAB/trunk/test/h5file

kraftche at cae.wisc.edu kraftche at cae.wisc.edu
Thu Apr 30 16:03:28 CDT 2009


Author: kraftche
Date: 2009-04-30 16:03:28 -0500 (Thu, 30 Apr 2009)
New Revision: 2864

Added:
   MOAB/trunk/test/h5file/h5partial.cpp
Modified:
   MOAB/trunk/test/h5file/Makefile.am
Log:
add tests for partial read of .h5m files

Modified: MOAB/trunk/test/h5file/Makefile.am
===================================================================
--- MOAB/trunk/test/h5file/Makefile.am	2009-04-30 21:03:14 UTC (rev 2863)
+++ MOAB/trunk/test/h5file/Makefile.am	2009-04-30 21:03:28 UTC (rev 2864)
@@ -3,7 +3,7 @@
 
 DEFS = $(DEFINES)
 INCLUDES += -I$(top_srcdir) -I$(top_srcdir)/mhdf/include -I$(top_builddir)
-check_PROGRAMS = h5test h5legacy h5varlen h5sets_test h5regression
+check_PROGRAMS = h5test h5legacy h5varlen h5sets_test h5regression h5partial
 
 TESTS = $(check_PROGRAMS)
 LDADD = $(top_builddir)/libMOAB.la
@@ -17,3 +17,4 @@
 h5varlen_SOURCES = h5varlen.cpp
 h5sets_test_SOURCES = h5sets_test.cpp
 h5regression_SOURCES = h5regression.cpp
+h5partial_SOURCES = h5partial.cpp

Added: MOAB/trunk/test/h5file/h5partial.cpp
===================================================================
--- MOAB/trunk/test/h5file/h5partial.cpp	                        (rev 0)
+++ MOAB/trunk/test/h5file/h5partial.cpp	2009-04-30 21:03:28 UTC (rev 2864)
@@ -0,0 +1,1263 @@
+#include "MBCore.hpp"
+#include "MBRange.hpp"
+#include "TestUtil.hpp"
+#include <vector>
+#include <stdlib.h>
+#include <iostream>
+#include <algorithm>
+#include <limits>
+
+const char TEST_FILE[] = "partial.h5m";
+const char READ_OPTS[] = "BUFFER_SIZE=256";
+const char ID_TAG_NAME[] = "test_id_tag";
+
+
+static void test_read_nothing_common( bool non_existant );
+static void test_read_nodes_common( int num_read_sets );
+static void test_read_handle_tag_common( bool var_len );
+
+const int QUAD_INT = 20; 
+const int NUM_SETS = 10;
+const int SET_WIDTH = (QUAD_INT + NUM_SETS - 1) / NUM_SETS; // ceil(QUAD_INT/NUM_SETS)
+const char LOGICAL_NAME[] = "logical";   // tag storing logical (i,j) coordinates
+const char CENTROID_NAME[] = "centroid"; // tag storing position of centroid (x,y,0)
+//! Create a regular QUAD_INT^2 element quad mesh with regularly
+//! spaced coordinates in the range [1,100].  Group elements
+//! into 10 vertical strips QUAD_INT/10 elements wide.  Tag elements,
+//! vertices and/or sets with ID in [1,10] stored in ID_TAG_NAME
+//! tag.  Write new mesh to TEST_FILE.
+void create_mesh( bool create_element_sets,
+                  bool create_vertex_sets,
+                  bool tag_elements_with_id,
+                  bool tag_vertices_with_id,
+                  const char* adj_elem_tag_name = 0,
+                  bool var_len_adj_elems = false );
+// Given a list of vertices adjacent to a quad strip, identify it as one of the 
+// NUM_SETS strips of quads written by create_mesh.
+int identify_set( MBInterface& mb, const MBRange& verts );
+int identify_set( MBInterface& mb, MBEntityHandle set );
+
+static MBTag check_tag( MBInterface& mb, 
+                        const char* name,
+                        MBTagType storage,
+                        MBDataType type,
+                        int size );
+
+enum ChildTestMode { CHILD_SETS, CHILD_CONTENTS, CHILD_NONE };
+void test_read_children_common( ChildTestMode mode );
+
+
+//! Read a set containing no entities
+void test_read_empty_set()
+  { test_read_nothing_common( false ); }
+  
+//! Specify ID that doesn't exist in file
+void test_read_non_existant_set()
+  { test_read_nothing_common( true ); }
+
+//! Read in the nodes contained in a set.
+void test_read_one_set_nodes()
+  { test_read_nodes_common(1); }
+
+//! Read in the elems contained in a set
+void test_read_one_set_elems();
+
+//! Read in the polyhedra contained in a set
+void test_read_one_set_polyhedra();
+
+//! Read in the sets contained in a set.  
+//! Should read all sets containing read elements or nodes
+//! and all sets that are contained the the specified "read"
+//! set.  Test the later here.
+void test_read_set_sets();
+
+//! Read in the nodes contained in a sets.
+void test_read_two_sets_nodes()
+  { test_read_nodes_common(2); }
+
+//! Read in the elems contained in a sets
+void test_read_two_sets_elems();
+
+//! For any set selected to be read by either explicit designation,
+//! containing read entities, or contained in an explcitly designated
+//! set, any child sets are also read.  Check that here.
+void test_read_child_sets_only()
+{ test_read_children_common( CHILD_SETS ); }
+void test_read_child_set_contents()
+{ test_read_children_common( CHILD_CONTENTS ); }
+void test_read_no_child_sets()
+{ test_read_children_common( CHILD_NONE ); }
+
+//! Read in the sets contained in a set.  
+//! Should read all sets containing read elements or nodes
+//! and all sets that are contained the the specified "read"
+//! set.  Test the former here.
+void test_read_containing_sets();
+
+//! Test reading of explicit adjacencies
+void test_read_adjacencies();
+
+//! Test reading of sparse double tag data
+void test_read_double_tag();
+
+//! Test reading of sparse opaque tag data
+void test_read_opaque_tag();
+
+//! Test reading of sparse handle tag data
+void test_read_handle_tag()
+  { test_read_handle_tag_common(false); }
+
+//! Test reading of variable-length tag data
+void test_var_len_tag()
+  { test_read_handle_tag_common(true); }
+
+void test_read_tagged_elems();
+
+void test_read_tagged_nodes();
+
+
+
+int main( int argc, char* argv[] )
+{
+  if (argc > 1) {
+    if (argc != 2 || strcmp(argv[1],"-k")) {
+      std::cerr << "Usage: " << argv[0] << " [-k]" << std::endl;
+      return 1;
+    }
+  }
+  
+  int result = 0;
+  
+  result += RUN_TEST(test_read_empty_set);
+  result += RUN_TEST(test_read_non_existant_set);
+  result += RUN_TEST(test_read_one_set_nodes);
+  result += RUN_TEST(test_read_one_set_elems);
+  result += RUN_TEST(test_read_one_set_polyhedra);
+  result += RUN_TEST(test_read_set_sets);
+  result += RUN_TEST(test_read_two_sets_nodes);
+  result += RUN_TEST(test_read_two_sets_elems);
+  result += RUN_TEST(test_read_child_sets_only);
+  result += RUN_TEST(test_read_child_set_contents);
+  result += RUN_TEST(test_read_no_child_sets);
+  result += RUN_TEST(test_read_containing_sets);
+  result += RUN_TEST(test_read_double_tag);
+  result += RUN_TEST(test_read_opaque_tag);
+  result += RUN_TEST(test_read_handle_tag);
+  result += RUN_TEST(test_var_len_tag);
+  result += RUN_TEST(test_read_adjacencies);
+  result += RUN_TEST(test_read_tagged_elems);
+  result += RUN_TEST(test_read_tagged_nodes);
+
+  if (argc == 1)
+    remove( TEST_FILE );
+  return result;
+}
+
+void test_read_nothing_common( bool non_existant )
+{
+  MBErrorCode rval;
+  MBCore moab;
+  MBInterface& mb = moab;
+
+  // create a few nodes to write to file
+  std::vector<double> coords( 3000 );
+  MBRange verts;
+  rval= mb.create_vertices( &coords[0], coords.size()/3, verts );
+  CHECK_ERR(rval);
+  
+  // create three entity sets
+  MBEntityHandle sets[3];
+  rval = mb.create_meshset( MESHSET_SET, sets[0] );
+  CHECK_ERR(rval);
+  rval = mb.create_meshset( MESHSET_SET, sets[1] );
+  CHECK_ERR(rval);
+  rval = mb.create_meshset( MESHSET_ORDERED, sets[2] );
+  CHECK_ERR(rval);
+  
+  // put all vertices into two of the sets
+  rval = mb.add_entities( sets[0], verts );
+  CHECK_ERR(rval);
+  rval = mb.add_entities( sets[2], verts );
+  CHECK_ERR(rval);
+  
+  // tag all three sets
+  MBTag id_tag;
+  rval = mb.tag_create( ID_TAG_NAME, sizeof(int), MB_TAG_SPARSE, MB_TYPE_INTEGER, id_tag, 0 );
+  CHECK_ERR(rval);
+  int ids[3] = { 5, 7, 9 };
+  rval = mb.tag_set_data( id_tag, sets, 3, ids );
+  CHECK_ERR(rval);
+  
+  // write mesh
+  rval = mb.write_file( TEST_FILE, "MOAB" );
+  CHECK_ERR(rval);
+  rval = mb.delete_mesh();
+  CHECK_ERR(rval);
+  
+  // now read back in only the empty set
+  MBEntityHandle file_set;
+  int id = non_existant ? 8 : 7;
+  rval = mb.load_file( TEST_FILE, file_set, READ_OPTS, ID_TAG_NAME, &id, 1 );
+  CHECK_ERR( rval );
+  
+  // the file should contain exactly two sets (the specified one and the new
+  // file set, and nothing else.)
+  for (MBEntityType t = MBVERTEX; t < MBENTITYSET; ++t) {
+    int count = -1;
+    rval = mb.get_number_entities_by_type( 0, t, count );
+    CHECK_ERR(rval);
+    CHECK_EQUAL( 0, count );
+  }
+  MBRange setrange;
+  rval = mb.get_entities_by_type( 0, MBENTITYSET, setrange );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( (non_existant ? 1 : 2), (int)setrange.size() );
+  CHECK( setrange.find(file_set) != setrange.end() );
+}
+
+
+static void vtx_coords( int set_id, int j, int num_sets, double coords[3] )
+{
+  int i = num_sets*j + set_id;
+  coords[0] = i;
+  coords[1] = i+0.25;
+  coords[2] = i+0.5;
+}
+
+void test_read_nodes_common( int num_read_sets )
+{
+  MBErrorCode rval;
+  MBCore moab;
+  MBInterface& mb = moab;
+    
+    // create 1000 nodes
+  const int num_sets = 2*num_read_sets;
+  std::vector<MBEntityHandle> verts(1000);
+  std::vector< std::vector<MBEntityHandle> > set_verts(num_sets);
+  for (size_t i = 0; i < verts.size(); ++i) {
+    double coords[3];
+    int j = i % num_sets;
+    vtx_coords( j+1, set_verts[j].size(), num_sets, coords );
+    rval = mb.create_vertex( coords, verts[i] );
+    set_verts[ j ].push_back( verts[i] );
+    CHECK_ERR(rval);
+  }
+  
+    // create two sets, each containing half of the nodes
+  std::vector<MBEntityHandle> sets(num_sets);
+  for (int i = 0; i < num_sets; ++i) {
+    rval = mb.create_meshset( MESHSET_ORDERED, sets[i] );
+    CHECK_ERR(rval);
+    rval = mb.add_entities( sets[i], &set_verts[i][0], set_verts[i].size() );
+    CHECK_ERR(rval);
+  }
+ 
+    // tag both sets
+  MBTag id_tag;
+  rval = mb.tag_create( ID_TAG_NAME, sizeof(int), MB_TAG_SPARSE, MB_TYPE_INTEGER, id_tag, 0 );
+  CHECK_ERR(rval);
+  std::vector<int> values( num_sets );
+  for (int i = 0; i < num_sets; ++i) values[i] = i+1;
+  rval = mb.tag_set_data( id_tag, &sets[0], num_sets, &values[0] );
+  CHECK_ERR(rval);
+  
+    // write file
+  rval = mb.write_file( TEST_FILE, "MOAB" );
+  CHECK_ERR(rval);
+  rval = mb.delete_mesh();
+  CHECK_ERR(rval);
+  
+    // now read back in only the specified number of sets
+  values.resize( num_read_sets );
+  for (int i = 0; i < num_read_sets; ++i) values[i] = 2*(i+1);
+  MBEntityHandle file_set;
+  rval = mb.load_file( TEST_FILE, file_set, READ_OPTS, ID_TAG_NAME, &values[0], num_read_sets );
+  CHECK_ERR(rval);
+  
+  int count, expected = 0;
+  rval = mb.get_number_entities_by_dimension( 0, 0, count );
+  CHECK_ERR(rval);
+  for (int i = 0; i < num_sets; ++i)
+    if (i % 2)
+      expected += set_verts[i].size();
+  CHECK_EQUAL( expected, count );
+  
+  MBRange sets2;
+  rval = mb.get_entities_by_type( 0, MBENTITYSET, sets2 );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( 1+num_read_sets, (int)sets2.size() );
+  MBRange::iterator it = sets2.find( file_set );
+  CHECK( it != sets2.end() );
+  sets2.erase( it );
+  
+  rval = mb.tag_get_handle( ID_TAG_NAME, id_tag );
+  CHECK_ERR(rval);  
+  while (!sets2.empty()) {
+    MBEntityHandle set = sets2.pop_front();
+    int id;
+    rval = mb.tag_get_data( id_tag, &set, 1, &id );
+    CHECK_ERR(rval);
+    CHECK( std::find(values.begin(), values.end(), id) != values.end() );
+    CHECK( id > 0 );
+    CHECK( (unsigned)id <= set_verts.size() );
+    
+    std::vector<MBEntityHandle> verts;
+    rval = mb.get_entities_by_handle( set, verts );
+    CHECK_ERR(rval);
+    CHECK_EQUAL( set_verts[id-1].size(), verts.size() );
+    
+    for (size_t i = 0; i < verts.size(); ++i) {
+      double exp_coords[3], coords[3];
+      vtx_coords( id, i, num_sets, exp_coords );
+      rval = mb.get_coords( &verts[i], 1, coords );
+      CHECK_ERR(rval);
+      CHECK_REAL_EQUAL( exp_coords[0], coords[0], 1e-12 );
+      CHECK_REAL_EQUAL( exp_coords[1], coords[1], 1e-12 );
+      CHECK_REAL_EQUAL( exp_coords[2], coords[2], 1e-12 );
+    }
+  }
+}
+
+//! Create a regular QUAD_INT^2 element quad mesh with regularly
+//! spaced coordinates in the range [1,100].  Group elements
+//! into 10 vertical strips QUAD_INT/10 elements wide.  Tag elements,
+//! vertices and/or sets with ID in [1,10] stored in ID_TAG_NAME
+//! tag.  Write new mesh to TEST_FILE.
+void create_mesh( bool create_element_sets,
+                  bool create_vertex_sets,
+                  bool tag_elements_with_id,
+                  bool tag_vertices_with_id,
+                  const char* adj_elem_tag_name,
+                  bool var_len_adj_elems )
+{
+  MBCore moab;
+  MBInterface& mb = moab;
+  MBErrorCode rval;
+  
+    // create tags
+  MBTag logical_tag, centroid_tag, id_tag;
+  rval = mb.tag_create( ID_TAG_NAME, sizeof(int), MB_TAG_SPARSE, MB_TYPE_INTEGER, id_tag, 0 );
+  CHECK_ERR(rval);
+  rval = mb.tag_create( LOGICAL_NAME, 2*sizeof(int), MB_TAG_DENSE, MB_TYPE_OPAQUE, logical_tag, 0 );
+  CHECK_ERR(rval);
+  rval = mb.tag_create( CENTROID_NAME, 3*sizeof(double), MB_TAG_DENSE, MB_TYPE_DOUBLE, centroid_tag, 0 );
+  CHECK_ERR(rval);
+
+  MBEntityHandle sets[NUM_SETS];
+  if (create_element_sets || create_vertex_sets) {
+    for (int i = 0; i < NUM_SETS; ++i) {
+      rval = mb.create_meshset( MESHSET_ORDERED, sets[i] );
+      CHECK_ERR(rval);
+      int id = i+1;
+      rval = mb.tag_set_data( id_tag, &sets[i], 1, &id );
+      CHECK_ERR(rval);
+    }
+  }
+
+    // create elements
+  MBEntityHandle verts[QUAD_INT+1][QUAD_INT+1], quads[QUAD_INT][QUAD_INT];
+  for (int i = 0; i <= QUAD_INT; ++i) for(int j = 0; j <= QUAD_INT; ++j) {
+    double coords[3] = { i, j, 0 };
+    rval = mb.create_vertex( coords, verts[j][i] );
+    CHECK_ERR(rval);
+    int logical[2] = { i, j };
+    rval = mb.tag_set_data( logical_tag, &verts[j][i], 1, logical );
+    CHECK_ERR(rval);
+    rval = mb.tag_set_data( centroid_tag, &verts[j][i], 1, coords );
+    CHECK_ERR(rval);
+    int id = (i-1)/SET_WIDTH + 1; // Note: assumes SET_WIDTH > 1
+    if (tag_vertices_with_id) {
+      rval = mb.tag_set_data( id_tag, &verts[j][i], 1, &id );
+      CHECK_ERR(rval);
+    }
+    if (create_vertex_sets) {
+      rval = mb.add_entities( sets[id-1], &verts[j][i], 1 );
+      CHECK_ERR(rval);
+        // Some vertices are shared by quads in different sets.
+        // put such vertices in both sets.
+      int id2 = i/SET_WIDTH + 1;
+      if (id2 != id && id2 <= NUM_SETS) {
+        rval = mb.add_entities( sets[id2-1], &verts[j][i], 1 );
+        CHECK_ERR(rval);
+      }
+    }
+  }
+  for (int i = 0; i < QUAD_INT; ++i) for(int j = 0; j < QUAD_INT; ++j) {
+    MBEntityHandle conn[4] = { verts[j  ][i  ], 
+                               verts[j  ][i+1],
+                               verts[j+1][i+1],
+                               verts[j+1][i  ] };
+    rval = mb.create_element( MBQUAD, conn, 4, quads[j][i] );
+    CHECK_ERR(rval);
+    int logical[2] = { i, j };
+    rval = mb.tag_set_data( logical_tag, &quads[j][i], 1, logical );
+    CHECK_ERR(rval);
+    double centroid[3] = { i + 0.5, j + 0.5, 0 };
+    rval = mb.tag_set_data( centroid_tag, &quads[j][i], 1, centroid );
+    CHECK_ERR(rval);
+    int id = i/SET_WIDTH + 1;
+    if (tag_elements_with_id) {
+      rval = mb.tag_set_data( id_tag, &quads[j][i], 1, &id );
+      CHECK_ERR(rval);
+    }
+    if (create_element_sets) {
+      rval = mb.add_entities( sets[id-1], &quads[j][i], 1 );
+      CHECK_ERR(rval);
+    }
+  }
+  
+  if (adj_elem_tag_name && !var_len_adj_elems) {
+    MBTag handle_tag;
+    rval = mb.tag_create( adj_elem_tag_name, 
+                          4 * sizeof(MBEntityHandle), 
+                          MB_TAG_DENSE,
+                          MB_TYPE_HANDLE,
+                          handle_tag,
+                          0 );
+    CHECK_ERR(rval);
+    for (int i = 0; i <= QUAD_INT; ++i) for(int j = 0; j <= QUAD_INT; ++j) {
+      MBEntityHandle val[4] = { (i > 0        && j > 0       ) ? quads[j-1][i-1] : 0,
+                                (i > 0        && j < QUAD_INT) ? quads[j  ][i-1] : 0,
+                                (i < QUAD_INT && j < QUAD_INT) ? quads[j  ][i  ] : 0,
+                                (i < QUAD_INT && j > 0       ) ? quads[j-1][i  ] : 0 };
+      rval = mb.tag_set_data( handle_tag, &verts[j][i], 1, val );
+      CHECK_ERR(rval);
+    }
+  }
+  else if (adj_elem_tag_name && var_len_adj_elems) {
+    MBTag handle_tag;
+    rval = mb.tag_create_variable_length( adj_elem_tag_name,
+                                          MB_TAG_DENSE,
+                                          MB_TYPE_HANDLE,
+                                          handle_tag );
+    CHECK_ERR(rval);
+    for (int i = 0; i <= QUAD_INT; ++i) for(int j = 0; j <= QUAD_INT; ++j) {
+      MBEntityHandle val[4];
+      int num = 0;
+      if (i > 0        && j > 0       ) val[num++] = quads[j-1][i-1];
+      if (i > 0        && j < QUAD_INT) val[num++] = quads[j  ][i-1];
+      if (i < QUAD_INT && j < QUAD_INT) val[num++] = quads[j  ][i  ];
+      if (i < QUAD_INT && j > 0       ) val[num++] = quads[j-1][i  ];
+      const void* ptr = val;
+      num *= sizeof(MBEntityHandle);
+      rval = mb.tag_set_data( handle_tag, &verts[j][i], 1, &ptr, &num );
+      CHECK_ERR(rval);
+    }
+  }
+  
+  rval = mb.write_file( TEST_FILE, "MOAB" );
+  CHECK_ERR(rval);
+}
+
+// Given a list of vertices adjacent to a quad strip, identify it as one of the 
+// NUM_SETS strips of quads written by create_mesh.
+int identify_set( MBInterface& mb, const MBRange& verts )
+{
+  const int COL = SET_WIDTH+1;
+  CHECK_EQUAL( (1+QUAD_INT)*COL, (int)verts.size() );
+
+    // Get X range of vertices
+  int min_x = std::numeric_limits<int>::max();
+  int max_x = std::numeric_limits<int>::min();
+  for (MBRange::const_iterator i = verts.begin(); i != verts.end(); ++i) {
+    double coords[3];
+    MBErrorCode rval = mb.get_coords( &*i, 1, coords );
+    CHECK_ERR(rval);
+      // Expect whole-valued coorindates
+    int int_x = (int)coords[0];
+    CHECK( fabs( coords[0] - (double)int_x ) < 1e-12 );
+    
+    if (int_x < min_x) min_x = int_x;
+    if (int_x > max_x) max_x = int_x;
+  }
+  CHECK( max_x - min_x < COL );
+  
+    // Calculate ID (return value) from coordinate range)
+  const int ID = min_x / SET_WIDTH + 1;
+  
+    // Now verify that all vertices correctly form a grid
+  MBEntityHandle grid[QUAD_INT+1][COL];
+  memset( grid, 0, sizeof(grid) );
+  for (MBRange::const_iterator i = verts.begin(); i != verts.end(); ++i) {
+    double coords[3];
+    MBErrorCode rval = mb.get_coords( &*i, 1, coords );
+    CHECK_ERR(rval);
+      // Expect whole-valued coorindates
+    int x = (int)coords[0] - (ID-1)*SET_WIDTH, y = (int)coords[1];
+    CHECK( fabs( coords[1] - (double)y ) < 1e-12 );
+    CHECK( fabs( coords[2] ) < 1e-12 );
+    CHECK( y >= 0 && y <= QUAD_INT );
+    CHECK_EQUAL( (MBEntityHandle)0, grid[y][x] );
+    grid[y][x] = *i;
+  }
+  
+  return ID;
+}
+int identify_set( MBInterface& mb, MBEntityHandle set )
+{
+  MBErrorCode rval;
+  MBRange verts, elems;
+  rval = mb.get_entities_by_handle( set, elems );
+  CHECK_ERR(rval);
+  MBRange::iterator it = elems.upper_bound( MBVERTEX );
+  verts.merge( elems.begin(), it );
+  elems.erase( elems.begin(), it );
+  it = elems.lower_bound( MBENTITYSET );
+  elems.erase( it, elems.end() );
+  rval = mb.get_adjacencies( elems, 0, false, verts, MBInterface::UNION );
+  CHECK_ERR(rval);
+  return identify_set( mb, verts );
+}
+
+//! Read in the elems contained in a set
+void test_read_one_set_elems()
+{
+  MBErrorCode rval;
+  MBCore moab;
+  MBInterface& mb = moab;
+  
+  create_mesh( true, false, false, false );
+  
+  for (int id = 1; id <= NUM_SETS; ++id) {
+    rval = mb.delete_mesh();
+    CHECK_ERR(rval);
+    MBEntityHandle file_set;
+    rval = mb.load_file( TEST_FILE, file_set, READ_OPTS, ID_TAG_NAME, &id, 1 );
+    CHECK_ERR(rval);
+    MBRange verts;
+    rval = mb.get_entities_by_type( 0, MBVERTEX, verts );
+    int act_id = identify_set( mb, verts );
+    CHECK_EQUAL( id, act_id );
+  }
+}
+
+//! Read in the elems contained in a sets
+void test_read_two_sets_elems()
+{
+  MBErrorCode rval;
+  MBCore moab;
+  MBInterface& mb = moab;
+  
+  create_mesh( true, false, false, false );
+  int ids[2] = { 2, 8 };
+  MBEntityHandle file_set;
+  rval = mb.load_file( TEST_FILE, file_set, READ_OPTS, ID_TAG_NAME, ids, 2 );
+  CHECK_ERR(rval);
+  
+  MBRange sets;
+  rval = mb.get_entities_by_type( 0, MBENTITYSET, sets );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( 3, (int)sets.size() );
+  MBRange::iterator it = sets.find( file_set );
+  CHECK( it != sets.end() );
+  sets.erase( it );
+  
+  int id1 = identify_set( mb, sets.front() );
+  int id2 = identify_set( mb, sets.back() );
+  if (id1 == ids[0]) {
+    CHECK_EQUAL( ids[1], id2 );
+  }
+  else {
+    CHECK_EQUAL( ids[1], id1 );
+    CHECK_EQUAL( ids[0], id2 );
+  }
+}
+
+MBTag check_tag( MBInterface& mb, 
+                 const char* name,
+                 MBTagType storage,
+                 MBDataType type,
+                 int size )
+{
+  
+  MBTag tag;
+  MBErrorCode rval = mb.tag_get_handle( name, tag );
+  CHECK_ERR(rval);
+
+  MBTagType storage1;
+  rval = mb.tag_get_type( tag, storage1 );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( storage, storage1 );
+  
+  MBDataType type1;
+  rval = mb.tag_get_data_type( tag, type1 );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( type, type1 );
+  
+  int size1;
+  rval = mb.tag_get_size( tag, size1 );
+  if (size < 0) { // variable-length tag
+    CHECK_EQUAL( MB_VARIABLE_DATA_LENGTH, rval );
+  }
+  else {
+    CHECK_ERR(rval);
+    CHECK_EQUAL( size, size1 );
+  }
+  
+  return tag;
+}
+
+//! Test reading of sparse double tag data
+void test_read_double_tag()
+{
+  MBErrorCode rval;
+  MBCore moab;
+  MBInterface& mb = moab;
+  
+  create_mesh( true, false, false, false );
+  int ids[2] = { 1, 4 };
+  MBEntityHandle file_set;
+  rval = mb.load_file( TEST_FILE, file_set, READ_OPTS, ID_TAG_NAME, ids, 2 );
+  CHECK_ERR(rval);
+  
+  MBTag tag = check_tag( mb, CENTROID_NAME, MB_TAG_DENSE, MB_TYPE_DOUBLE, 3*sizeof(double) );
+  MBRange verts;
+  rval = mb.get_entities_by_type( 0, MBVERTEX, verts );
+  CHECK_ERR(rval);
+  CHECK( !verts.empty() );
+  for (MBRange::iterator i = verts.begin(); i != verts.end(); ++i) {
+    double coords[3], data[3];
+    rval = mb.get_coords( &*i, 1, coords );
+    CHECK_ERR(rval);
+    rval = mb.tag_get_data( tag, &*i, 1, data );
+    CHECK_ERR(rval);
+    CHECK_REAL_EQUAL( coords[0], data[0], 1e-12 );
+    CHECK_REAL_EQUAL( coords[1], data[1], 1e-12 );
+    CHECK_REAL_EQUAL( coords[2], data[2], 1e-12 );
+  }
+}
+
+//! Test reading of sparse opaque tag data
+void test_read_opaque_tag()
+{
+  MBErrorCode rval;
+  MBCore moab;
+  MBInterface& mb = moab;
+  
+  create_mesh( true, false, false, false );
+  int ids[2] = { 1, 4 };
+  MBEntityHandle file_set;
+  rval = mb.load_file( TEST_FILE, file_set, READ_OPTS, ID_TAG_NAME, ids, 2 );
+  CHECK_ERR(rval);
+
+  MBTag tag = check_tag( mb, LOGICAL_NAME, MB_TAG_DENSE, MB_TYPE_OPAQUE, 2*sizeof(int) );
+  MBRange verts;
+  rval = mb.get_entities_by_type( 0, MBVERTEX, verts );
+  CHECK_ERR(rval);
+  CHECK( !verts.empty() );
+  for (MBRange::iterator i = verts.begin(); i != verts.end(); ++i) {
+    double coords[3];
+    int data[2];
+    rval = mb.get_coords( &*i, 1, coords );
+    CHECK_ERR(rval);
+    rval = mb.tag_get_data( tag, &*i, 1, data );
+    CHECK_ERR(rval);
+    CHECK_REAL_EQUAL( coords[0], (double)data[0], 1e-12 );
+    CHECK_REAL_EQUAL( coords[1], (double)data[1], 1e-12 );
+  }
+}
+
+static void test_read_handle_tag_common( bool var_len )
+{
+  MBErrorCode rval;
+  MBCore moab;
+  MBInterface& mb = moab;
+  
+  const char tag_name[] = "VTX_ADJ";
+  create_mesh( true, false, false, false, tag_name, var_len );
+  int ids[2] = { 7, 10 };
+  MBEntityHandle file_set;
+  rval = mb.load_file( TEST_FILE, file_set, READ_OPTS, ID_TAG_NAME, ids, 2 );
+  CHECK_ERR(rval);
+  
+  MBTag tag = check_tag( mb, tag_name, MB_TAG_DENSE, MB_TYPE_HANDLE, 
+                         var_len ? -1 : 4*sizeof(MBEntityHandle) );
+  MBRange verts;
+  rval = mb.get_entities_by_type( 0, MBVERTEX, verts );
+  CHECK_ERR(rval);
+  CHECK( !verts.empty() );
+  for (MBRange::iterator i = verts.begin(); i != verts.end(); ++i) {
+    std::vector<MBEntityHandle> adj, val;
+    rval = mb.get_adjacencies( &*i, 1, 2, false, adj, MBInterface::UNION );
+    CHECK_ERR(rval);
+    CHECK(!adj.empty());
+    
+    int num;
+    const void* ptr;
+    rval = mb.tag_get_data( tag, &*i, 1, &ptr, &num );
+    CHECK_ERR(rval);
+    CHECK_EQUAL( 0, num % (int)sizeof(MBEntityHandle) );
+    num /= sizeof(MBEntityHandle);
+    
+    if (var_len) {
+      CHECK( num > 0 );
+      CHECK( num < 5 );
+    }
+    else {
+      CHECK_EQUAL( 4, num );
+    }
+    
+    val.clear();
+    const MBEntityHandle* dat = (const MBEntityHandle*)ptr;
+    for (const MBEntityHandle* end = dat+num; dat != end; ++dat)
+      if (*dat)
+        val.push_back(*dat);
+
+    CHECK_EQUAL( adj.size(), val.size() );
+    std::sort( adj.begin(), adj.end() );
+    std::sort( val.begin(), val.end() );
+    CHECK( adj == val );
+  }
+}
+
+
+void test_read_tagged_elems()
+{
+  MBErrorCode rval;
+  MBCore moab;
+  MBInterface& mb = moab;
+  
+  create_mesh( false, false, true, false );
+  int id = 5;
+  MBEntityHandle file_set;
+  rval = mb.load_file( TEST_FILE, file_set, READ_OPTS, ID_TAG_NAME, &id, 1 );
+  CHECK_ERR(rval);
+  
+  MBRange verts;
+  rval = mb.get_entities_by_type( 0, MBVERTEX, verts );
+  CHECK_ERR(rval);
+  int id2 = identify_set( mb, verts );
+  CHECK_EQUAL( id, id2 );
+  
+  int elems;
+  rval = mb.get_number_entities_by_type( 0, MBQUAD, elems );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( QUAD_INT*QUAD_INT/NUM_SETS, elems );
+}
+
+void test_read_tagged_nodes()
+{
+  MBErrorCode rval;
+  MBCore moab;
+  MBInterface& mb = moab;
+  
+  create_mesh( false, false, false, true );
+  int id = 1; // NOTE: this test will only succeed for ID == 1 
+  MBEntityHandle file_set;
+  rval = mb.load_file( TEST_FILE, file_set, READ_OPTS, ID_TAG_NAME, &id, 1 );
+  CHECK_ERR(rval);
+  
+  MBRange verts;
+  rval = mb.get_entities_by_type( 0, MBVERTEX, verts );
+  CHECK_ERR(rval);
+  int id2 = identify_set( mb, verts );
+  CHECK_EQUAL( id, id2 );
+  
+  int elems;
+  rval = mb.get_number_entities_by_type( 0, MBQUAD, elems );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( QUAD_INT*QUAD_INT/NUM_SETS, elems );
+}
+
+
+//! Read in the polyhedra contained in a set
+void test_read_one_set_polyhedra()
+{
+  MBErrorCode rval;
+  MBCore instance;
+  MBInterface& mb = instance;
+  
+    // create a 2x2x1 block of hexes, splitting each hex face
+    // into two triangles to form an 12-sided polyhedron
+  MBEntityHandle verts[18], hexes[4];
+  double coords[18][3] = { {0, 0, 0},
+                           {1, 0, 0},
+                           {2, 0, 0},
+                           {0, 1, 0},
+                           {1, 1, 0},
+                           {2, 1, 0},
+                           {0, 0, 1},
+                           {1, 0, 1},
+                           {2, 0, 1},
+                           {0, 1, 1},
+                           {1, 1, 1},
+                           {2, 1, 1},
+                           {0, 0, 2},
+                           {1, 0, 2},
+                           {2, 0, 2},
+                           {0, 1, 2},
+                           {1, 1, 2},
+                           {2, 1, 2} };
+  int hexconn[4][8] = {  { 0, 1, 4, 3, 6, 7, 10, 9 },
+                         { 1, 2, 5, 4, 7, 8, 11, 10 },
+                         { 6, 7, 10, 9, 12, 13, 16, 15 },
+                         { 7, 8, 11, 10, 13, 14, 17, 16 } };
+  for (int i = 0; i < 18; ++i) {
+    rval = mb.create_vertex( coords[i], verts[i] );
+    CHECK_ERR(rval);
+  }
+  for (int i = 0; i < 4; ++i) {
+    MBEntityHandle conn[8];
+    for (int j = 0; j < 8; ++j)
+      conn[j] = verts[hexconn[i][j]];
+    rval = mb.create_element( MBHEX, conn, 8, hexes[i] );
+    CHECK_ERR(rval);
+  }
+  
+  MBTag tri_tag;
+  rval = mb.tag_create( "tris", 2*sizeof(MBEntityHandle), MB_TAG_SPARSE, MB_TYPE_HANDLE, tri_tag, 0 );
+  CHECK_ERR(rval);
+  
+  std::vector<MBEntityHandle> quads;
+  MBEntityHandle tris[12], poly[4];
+  for (int i = 0; i < 4; ++i) {
+    quads.clear();
+    rval = mb.get_adjacencies( &hexes[i], 1, 2, true, quads );
+    CHECK_ERR(rval);
+    CHECK_EQUAL( 6, (int)quads.size() );
+    
+    for (int j = 0; j < 6; ++j) {
+      rval = mb.tag_get_data( tri_tag, &quads[j], 1, tris + 2*j );
+      if (MB_SUCCESS == rval)
+        continue;
+      CHECK_EQUAL( MB_TAG_NOT_FOUND, rval );
+      const MBEntityHandle* conn;
+      int len;
+      rval = mb.get_connectivity( quads[j], conn, len );
+      CHECK_ERR(rval);
+      CHECK_EQUAL( 4, len );
+      MBEntityHandle tri_conn[2][3] = {  { conn[0], conn[1], conn[2] },
+                                         { conn[2], conn[3], conn[0] } };
+      rval = mb.create_element( MBTRI, tri_conn[0], 3, tris[2*j  ] ); CHECK_ERR(rval);
+      rval = mb.create_element( MBTRI, tri_conn[1], 3, tris[2*j+1] ); CHECK_ERR(rval);
+      rval = mb.tag_set_data( tri_tag, &quads[j], 1, tris + 2*j ); CHECK_ERR(rval);
+    }
+    
+    rval = mb.create_element( MBPOLYHEDRON, tris, 12, poly[i] );
+    CHECK_ERR(rval);
+  }
+  
+  MBRange all_tri;
+  rval = mb.get_entities_by_type( 0, MBTRI, all_tri );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( 40, (int)all_tri.size() );
+  
+  rval = mb.delete_entities( hexes, 4 ); CHECK_ERR(rval);
+  rval = mb.delete_entities( &quads[0], quads.size() ); CHECK_ERR(rval);
+  
+  MBEntityHandle sets[2];
+  rval = mb.create_meshset( 0, sets[0] ); CHECK_ERR(rval);
+  rval = mb.add_entities( sets[0], poly, 2 ); CHECK_ERR(rval);
+  rval = mb.create_meshset( 0, sets[1] ); CHECK_ERR(rval);
+  rval = mb.add_entities( sets[1], poly+2, 2 ); CHECK_ERR(rval);
+  
+  MBTag id_tag;
+  rval = mb.tag_create( ID_TAG_NAME, sizeof(int), MB_TAG_SPARSE, MB_TYPE_INTEGER, id_tag, 0 );
+  CHECK_ERR(rval);
+  int ids[2] = { 2, 3 };
+  rval = mb.tag_set_data( id_tag, sets, 2, ids ); CHECK_ERR(rval);
+  
+  rval = mb.write_file( TEST_FILE, "MOAB" );
+  CHECK_ERR(rval);
+  rval = mb.delete_mesh();
+  CHECK_ERR(rval);
+  
+  MBEntityHandle file;
+  rval = mb.load_file( TEST_FILE, file, READ_OPTS, ID_TAG_NAME, ids, 1 );
+  CHECK_ERR(rval);
+  
+  MBRange rpoly;
+  rval = mb.get_entities_by_type( 0, MBPOLYHEDRON, rpoly );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( 2, (int)rpoly.size() );
+  
+  MBRange polyverts;
+  rval = mb.get_adjacencies( rpoly, 0, false, polyverts, MBInterface::UNION );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( 12, (int)polyverts.size() );
+  
+  for (MBRange::iterator it = polyverts.begin(); it != polyverts.end(); ++it) {
+    double coords2[3];
+    rval = mb.get_coords( &*it, 1, coords2 );
+    CHECK_ERR(rval);
+    CHECK( coords2[0] > -1e-12 && coords2[0]-2 < 1e-12 );
+    CHECK( coords2[1] > -1e-12 && coords2[1]-1 < 1e-12 );
+    CHECK( coords2[2] > -1e-12 && coords2[2]-1 < 1e-12 );
+  }
+}
+
+//! Read in the sets contained in a set.  
+//! Should read all sets containing read elements or nodes
+//! and all sets that are contained the the specified "read"
+//! set.  Test the later here.
+void test_read_set_sets()
+{
+  MBErrorCode rval;
+  MBCore instance;
+  MBInterface& mb = instance;
+  
+  MBTag id_tag;
+  rval = mb.tag_create( ID_TAG_NAME, sizeof(int), MB_TAG_SPARSE, MB_TYPE_INTEGER, id_tag, 0 );
+  CHECK_ERR(rval);
+  
+    // create sets and assign an ID to each
+  const int len = 5;
+  MBEntityHandle set[2*len+2];
+  for (int i = 0; i < 2*len+2; ++i) {
+    rval = mb.create_meshset( MESHSET_SET, set[i] );
+    CHECK_ERR(rval);
+    int id = i + 1;
+    rval = mb.tag_set_data( id_tag, set + i, 1, &id );
+    CHECK_ERR(rval);
+  }
+  
+    // make set containment as follows (values are assigned IDs):
+  int cont_ids[2][len] = { { 3, 4, 5, 9, 10 }, { 6, 7, 8, 11, 12 } };
+  for (int i = 0; i < 2; ++i) {
+    MBEntityHandle contents[len] = { set[cont_ids[i][0] - 1],
+                                     set[cont_ids[i][1] - 1],
+                                     set[cont_ids[i][2] - 1],
+                                     set[cont_ids[i][3] - 1],
+                                     set[cont_ids[i][4] - 1] };
+    rval = mb.add_entities( set[i], contents, len );
+    CHECK_ERR(rval);
+  }
+  
+  rval = mb.write_file( TEST_FILE, "MOAB" );
+  CHECK_ERR(rval);
+  
+  for (int i = 0; i < 2; ++i) {
+    rval = mb.delete_mesh();
+    CHECK_ERR(rval);
+    
+    MBEntityHandle file;
+    int id = i+1;
+    rval = mb.load_file( TEST_FILE, file, READ_OPTS, ID_TAG_NAME, &id, 1 );
+    CHECK_ERR(rval);
+    
+      // check that the total number of sets read is as expected
+    MBRange sets;
+    rval = mb.get_entities_by_type( 0, MBENTITYSET, sets );
+    CHECK_ERR(rval);
+    MBRange::iterator it = sets.find( file );
+    if (it != sets.end())
+      sets.erase( it );
+    CHECK_EQUAL( len+1, (int)sets.size() );
+    
+      // check that we read in the set specified by ID to the reader
+    rval = mb.tag_get_handle( ID_TAG_NAME, id_tag );
+    CHECK_ERR(rval);
+    sets.clear();
+    const void* data[] = { &id };
+    rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &id_tag, data, 1, sets );
+    CHECK_ERR(rval);
+    CHECK_EQUAL( 1, (int)sets.size() );
+      
+      // check that it contains the expected sets
+    MBEntityHandle owner = sets.front();
+    sets.clear();
+    rval = mb.get_entities_by_type( owner, MBENTITYSET, sets );
+    CHECK_ERR(rval);
+    CHECK_EQUAL( len, (int)sets.size() );
+    
+    std::vector<int> expected( cont_ids[i], cont_ids[i] + len );
+    std::vector<int> actual( len );
+    rval = mb.tag_get_data( id_tag, sets, &actual[0] );
+    CHECK_ERR(rval);
+    std::sort( expected.begin(), expected.end() );
+    std::sort( actual.begin(), actual.end() );
+    CHECK( expected == actual );
+  }
+}
+
+static void check_children( ChildTestMode mode, MBInterface& mb, int id, MBTag id_tag, MBEntityHandle file )
+{
+  const int exp_num_sets = (mode == CHILD_NONE) ? 1 : id;
+  const int exp_num_edges = (mode == CHILD_CONTENTS) ? id : 1;
+  
+  MBErrorCode rval;
+  MBRange range;
+  rval = mb.get_entities_by_type( 0, MBEDGE , range );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( exp_num_edges, (int)range.size() );
+  range.clear();
+  rval = mb.get_entities_by_type( 0, MBENTITYSET , range );
+  CHECK_ERR(rval);
+  MBRange::iterator it = range.find( file );
+  CHECK( it != range.end() );
+  range.erase( it );
+  CHECK_EQUAL( exp_num_sets, (int)range.size() );
+  
+  MBEntityHandle set;
+  const void* val[] = {&id};
+  range.clear();
+  rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &id_tag, val, 1, range );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( 1, (int)range.size() );
+  set = range.front();
+  
+  if (mode == CHILD_NONE) {
+    range.clear();
+    rval = mb.get_entities_by_type( set, MBEDGE , range );
+    CHECK_ERR(rval);
+    CHECK_EQUAL( 1, (int)range.size() );
+    return;
+  }
+  
+  for (int i = id; i > 0; --i) {
+    int act_id;
+    rval = mb.tag_get_data( id_tag, &set, 1, &act_id );
+    CHECK_ERR(rval);
+    CHECK_EQUAL( i, act_id );
+
+    range.clear();
+    rval = mb.get_entities_by_type( set, MBEDGE, range );
+    CHECK_ERR(rval);
+    if (mode == CHILD_CONTENTS || i == id) {
+      CHECK_EQUAL( 1, (int)range.size() );
+      const MBEntityHandle* conn;
+      int len;
+      rval = mb.get_connectivity( range.front(), conn, len );
+      CHECK_ERR(rval);
+      CHECK_EQUAL( 2, len );
+      double coords[3];
+      rval = mb.get_coords( conn + 1, 1, coords );
+      CHECK_ERR(rval);
+      CHECK_EQUAL( i, (int)coords[0] );
+    }
+    else {
+      CHECK( range.empty() );
+    }
+      
+    std::vector<MBEntityHandle> children;
+    rval = mb.get_child_meshsets( set, children );
+    CHECK_ERR(rval);
+    if (i == 1) {
+      CHECK( children.empty() );
+    }
+    else {
+      CHECK_EQUAL( 1, (int)children.size() );
+      set = children[0];
+    }
+  } 
+}
+
+
+const char* set_read_opts[] = { "SETS", "CONTENTS", "NONE" };
+void test_read_children_common( ChildTestMode mode )
+{
+  MBErrorCode rval;
+  MBCore instance;
+  MBInterface& mb = instance;
+  
+  MBTag id_tag;
+  rval = mb.tag_create( ID_TAG_NAME, sizeof(int), MB_TAG_SPARSE, MB_TYPE_INTEGER, id_tag, 0 );
+  CHECK_ERR(rval);
+  
+    // Create a string of edges from [0,INT] along the X axis each 1 unit in length.
+    // Create a set for edge edge, containing the edge and the parent of the 
+    // set containing the previous (closer to origin) edge.  Assign each set an
+    // ID that is the X coordinate of the larger of the two vertices of the edge
+    // contained in the set.
+  const int INT = 64;
+  MBEntityHandle verts[INT+1], edges[INT], sets[INT];
+  double coords[] = { 0, 0, 0 };
+  rval = mb.create_vertex( coords, verts[0] );
+  CHECK_ERR(rval);
+  for (int i = 0; i < INT; ++i) {
+    const int id = i + 1;
+    coords[0] = id;
+    rval = mb.create_vertex( coords, verts[id] );
+    CHECK_ERR(rval);
+    rval = mb.create_element( MBEDGE, verts + i, 2, edges[i] );
+    CHECK_ERR(rval);
+    rval = mb.create_meshset( MESHSET_SET, sets[i] );
+    CHECK_ERR(rval);
+    rval = mb.add_entities( sets[i], edges + i, 1 );
+    CHECK_ERR(rval);
+    rval = mb.tag_set_data( id_tag, sets + i, 1, &id );
+    CHECK_ERR(rval);
+    if (i > 0) {
+      rval = mb.add_child_meshset( sets[i], sets[i-1] );
+      CHECK_ERR(rval);
+    }
+  }
+  
+    // Write the data
+  rval = mb.write_file( TEST_FILE, "MOAB" );
+  CHECK_ERR(rval);
+ 
+  MBEntityHandle file;
+  std::string opt( READ_OPTS );
+  opt += ";CHILDREN=";
+  opt += set_read_opts[mode];
+
+  const int test_ids[] = { 2, 7, INT/3-1, INT/2+1, INT-3 };
+  const int num_test_ids = sizeof(test_ids)/sizeof(int);
+  for (int i = 0; i < num_test_ids; ++i) {
+    CHECK (test_ids[i] <= INT);
+    
+    rval = mb.delete_mesh();
+    CHECK_ERR(rval);
+    
+    rval = mb.load_file( TEST_FILE, file, opt.c_str(), ID_TAG_NAME, test_ids+i, 1 );
+    CHECK_ERR(rval);
+    rval = mb.tag_get_handle( ID_TAG_NAME, id_tag );
+    CHECK_ERR(rval);
+    
+    check_children( mode, mb, test_ids[i], id_tag, file );
+  }
+}
+
+static void check_num_verts( MBInterface& mb, MBTag tag, int id, int num_vtx )
+{
+  MBErrorCode rval;
+  const void* val[] = {&id};
+  MBRange range;
+  rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &tag, val, 1, range );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( 1, (int)range.size() );
+
+  MBEntityHandle set = range.front();
+  range.clear();
+  rval = mb.get_entities_by_type( set, MBVERTEX, range );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( num_vtx, (int)range.size() );
+}
+
+
+//! Read in the sets contained in a set.  
+//! Should read all sets containing read elements or nodes
+//! and all sets that are contained the the specified "read"
+//! set.  Test the former here.
+void test_read_containing_sets()
+{
+    // create mesh decomposed by elements but create
+    // sets containing all vertices of decomposed elements
+    // such that adjacent sets share vertices.
+  create_mesh( false, true, false, false );
+  
+  MBErrorCode rval;
+  MBCore instance;
+  MBInterface& mb = instance;
+  
+    // read some sets
+  MBEntityHandle file;
+  const int ids[] = { 1, 5, 9 };
+  const int num_sets = sizeof(ids)/sizeof(int);
+  rval = mb.load_file( TEST_FILE, file, READ_OPTS, ID_TAG_NAME, ids, num_sets );
+  CHECK_ERR(rval);
+
+  MBTag id_tag;
+  rval = mb.tag_get_handle( ID_TAG_NAME, id_tag );
+  CHECK_ERR(rval);
+  
+    // expect all sets adjacent to the specified sets because
+    // they share vertices.
+  MBRange verts;
+  for (int i = 0; i < num_sets; ++i) {
+    if (ids[i] > 1)
+      check_num_verts( mb, id_tag, ids[i]-1, QUAD_INT+1 );
+    check_num_verts( mb, id_tag, ids[i], (QUAD_INT+1)*(SET_WIDTH+1) );
+    if (ids[i] < NUM_SETS)
+      check_num_verts( mb, id_tag, ids[i]+1, QUAD_INT+1 );
+  }
+}
+
+//! Test reading of explicit adjacencies
+void test_read_adjacencies()
+{
+  MBErrorCode rval;
+  MBCore instance;
+  MBInterface& mb = instance;
+  
+    // create four hexes sharing an edge
+  MBEntityHandle verts[3][3][2], hexes[2][2];
+  for (int k = 0; k < 2; ++k) {
+    for (int j = 0; j < 3; ++j) {
+      for (int i = 0; i < 3; ++i) {
+        double coords[] = { i, j, k };
+        rval = mb.create_vertex( coords, verts[i][j][k] );
+        CHECK_ERR(rval);
+      }
+    }
+  }
+  for (int j = 0; j < 2; ++j) {
+    for (int i = 0; i < 2; ++i) {
+      MBEntityHandle conn[] = { verts[i  ][j  ][0],
+                                verts[i+1][j  ][0],
+                                verts[i+1][j+1][0],
+                                verts[i  ][j+1][0],
+                                verts[i  ][j  ][1],
+                                verts[i+1][j  ][1],
+                                verts[i+1][j+1][1],
+                                verts[i  ][j+1][1] };
+      rval = mb.create_element( MBHEX, conn, 8, hexes[i][j] );
+      CHECK_ERR(rval);
+    }
+  }
+  
+    // create two duplicate edges that connect the vertices common to all four hexes
+  MBEntityHandle edge_conn[2] = { verts[1][1][0], verts[1][1][1] };
+  MBEntityHandle edges[2];
+  rval = mb.create_element( MBEDGE, edge_conn, 2, edges[0] ); CHECK_ERR(rval);
+  rval = mb.create_element( MBEDGE, edge_conn, 2, edges[1] ); CHECK_ERR(rval);
+    // mark one edge as adjacent to the left two hexes and the
+    // other as adjacent to the right two
+  rval = mb.add_adjacencies( edges[0], hexes[0], 2, true ); CHECK_ERR(rval);
+  rval = mb.add_adjacencies( edges[1], hexes[1], 2, true ); CHECK_ERR(rval);
+    // create two sets containing the front two and the rear two
+    // hexes, respectively.
+  MBEntityHandle sets[2];
+  rval = mb.create_meshset( MESHSET_SET, sets[0] ); CHECK_ERR(rval);
+  rval = mb.create_meshset( MESHSET_SET, sets[1] ); CHECK_ERR(rval);
+  MBEntityHandle set1[4] = { hexes[0][0], hexes[1][0], edges[0], edges[1] };
+  MBEntityHandle set2[4] = { hexes[0][1], hexes[1][1], edges[0], edges[1] };
+  rval = mb.add_entities( sets[0], set1, 4 ); CHECK_ERR(rval);
+  rval = mb.add_entities( sets[1], set2, 4 ); CHECK_ERR(rval);
+  
+    // assign IDs to sets
+  MBTag id_tag;
+  rval = mb.tag_create( ID_TAG_NAME, sizeof(int), MB_TAG_SPARSE, MB_TYPE_INTEGER, id_tag, 0 );
+  CHECK_ERR(rval);
+  int ids[2] = { 1, 2 };
+  rval = mb.tag_set_data( id_tag, sets, 2, ids );
+  CHECK_ERR(rval);
+  
+    // write mesh
+  rval = mb.write_file( TEST_FILE, "MOAB" );
+  CHECK_ERR(rval);
+  
+    // read mesh
+  rval = mb.delete_mesh(); CHECK_ERR(rval);
+  MBEntityHandle file;
+  rval = mb.load_file( TEST_FILE, file, READ_OPTS, ID_TAG_NAME, ids, 1 );
+  CHECK_ERR(rval);
+  
+    // expect two hexes and two edges
+  MBRange range;
+  rval = mb.get_entities_by_type( 0, MBHEX, range );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( 2, (int)range.size() );
+  MBEntityHandle h1 = range.front(), h2 = range.back();
+  range.clear();
+  rval = mb.get_entities_by_type( 0, MBEDGE, range );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( 2, (int)range.size() );
+ 
+    // expecte each edge to have one of the hexes
+  range.clear();
+  rval = mb.get_adjacencies( &h1, 1, 1, false, range );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( 1, (int)range.size() ); 
+  MBEntityHandle e1 = range.front();
+  range.clear();
+  rval = mb.get_adjacencies( &h2, 1, 1, false, range );
+  CHECK_ERR(rval);
+  CHECK_EQUAL( 1, (int)range.size() ); 
+  MBEntityHandle e2 = range.front();
+  
+  CHECK( e1 != e2 );
+}
+
+



More information about the moab-dev mailing list