[MOAB-dev] r2245 - MOAB/trunk/tools/iMesh

kraftche at mcs.anl.gov kraftche at mcs.anl.gov
Thu Nov 13 21:24:24 CST 2008


Author: kraftche
Date: 2008-11-13 21:24:24 -0600 (Thu, 13 Nov 2008)
New Revision: 2245

Modified:
   MOAB/trunk/tools/iMesh/iMeshP_unit_tests.cpp
Log:
o Consolidate some test code
o Group utility methods together
o Test iMeshP_getNumCopies
o Test iMeshP_getCopyParts
o Test iMeshP_getCopies
o Test iMeshP_getCopyOnPart
o Test iMeshP_getOwnerCopy


Modified: MOAB/trunk/tools/iMesh/iMeshP_unit_tests.cpp
===================================================================
--- MOAB/trunk/tools/iMesh/iMeshP_unit_tests.cpp	2008-11-14 03:22:42 UTC (rev 2244)
+++ MOAB/trunk/tools/iMesh/iMeshP_unit_tests.cpp	2008-11-14 03:24:24 UTC (rev 2245)
@@ -182,6 +182,12 @@
  * Test:
  * - iMeshP_getNumCopies
  * - iMeshP_getCopyParts
+ */
+int test_entity_copy_parts( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
+
+/**\brief Test information about entity copies for interface entities
+ *
+ * Test:
  * - iMeshP_getCopies
  * - iMeshP_getCopyOnPart
  * - iMeshP_getOwnerCopy
@@ -289,6 +295,96 @@
   return iBase_SUCCESS;
 }
 
+
+static int get_entities( iMesh_Instance imesh,
+                         iBase_EntitySetHandle set,
+                         iBase_EntityType type,
+                         iMesh_EntityTopology topo,
+                         std::vector<iBase_EntityHandle>& entities )
+{
+  iBase_EntitySetHandle* array = 0;
+  int junk = 0, size = 0, err;
+  iMesh_getEntities( imesh, set, type, topo, &array, &junk, &size, &err );
+  if (!err) {
+    entities.clear();
+    entities.resize( size );
+    std::copy( array, array + size, entities.begin() );
+    free( array );
+  }
+  return err;
+}
+
+static int get_intersection( iMesh_Instance imesh,
+                             iBase_EntitySetHandle set1,
+                             iBase_EntitySetHandle set2,
+                             iBase_EntityType type,
+                             iMesh_EntityTopology topo,
+                             std::vector<iBase_EntityHandle>& entities )
+{
+  std::vector<iBase_EntityHandle> l1, l2;
+  int err;
+  err = get_entities( imesh, set1, type, topo, l1 );
+  if (err)
+    return err;
+  err = get_entities( imesh, set2, type, topo, l2 );
+  if (err)
+    return err;
+  
+  std::sort( l1.begin(), l1.end() );
+  std::sort( l2.begin(), l2.end() );
+  std::set_intersection( l1.begin(), l1.end(),
+                         l2.begin(), l2.end(),
+                         std::back_inserter( entities ) );
+  return iBase_SUCCESS;
+}
+
+static int get_part_quads_and_verts( iMesh_Instance imesh,
+                                     iMeshP_PartHandle part,
+                                     std::vector<iBase_EntityHandle>& elems,
+                                     std::vector<iBase_EntityHandle>& verts )
+{
+  int ierr = get_entities( imesh, part, iBase_FACE, iMesh_QUADRILATERAL, elems );
+  CHKERR;
+  
+  verts.resize(4*elems.size());
+  std::vector<int> junk(elems.size()+1);
+  int junk1 = verts.size(), count, junk2 = junk.size(), junk3;
+  iBase_EntityHandle* junk4 = &verts[0];
+  int* junk5 = &junk[0];
+  iMesh_getEntArrAdj( imesh, &elems[0], elems.size(), iBase_VERTEX,
+                      &junk4, &junk1, &count,
+                      &junk5, &junk2, &junk3, &ierr );
+  CHKERR;
+  assert( junk1 == (int)verts.size() );
+  assert( count == (int)(4*elems.size()) );
+  assert( junk2 == (int)junk.size() );
+  assert( junk4 == &verts[0] );
+  assert( junk5 == &junk[0] );
+  std::sort( verts.begin(), verts.end() );
+  verts.erase( std::unique( verts.begin(), verts.end() ), verts.end() );
+  return iBase_SUCCESS;
+}
+  
+static int get_coords( iMesh_Instance imesh,
+                       const iBase_EntityHandle* verts,
+                       int num_verts,
+                       double* coords )
+{
+  double* junk1 = coords;
+  int junk2 = 3*num_verts;
+  int junk3;
+  int junk4 = iBase_INTERLEAVED;
+  int ierr;
+  iMesh_getVtxArrCoords( imesh, verts, num_verts, &junk4, &junk1, &junk2, &junk3, &ierr );
+  if (iBase_SUCCESS != ierr)
+    return ierr;
+  assert( junk1 == coords );
+  assert( junk2 == 3*num_verts );
+  assert( junk3 == 3*num_verts );
+  assert( junk4 == iBase_INTERLEAVED );
+  return iBase_SUCCESS;
+}
+  
 /**************************************************************************
                               Main Method
  **************************************************************************/
@@ -385,6 +481,7 @@
   num_errors += RUN_TEST( test_entity_iterator );
   num_errors += RUN_TEST( test_entity_owner );
   num_errors += RUN_TEST( test_entity_status );
+  num_errors += RUN_TEST( test_entity_copy_parts );
   num_errors += RUN_TEST( test_entity_copies );
   num_errors += RUN_TEST( test_create_ghost_ents );
   num_errors += RUN_TEST( test_push_tag_data );
@@ -561,79 +658,8 @@
   
   return 0;
 }
-
-
-static int get_entities( iMesh_Instance imesh,
-                         iBase_EntitySetHandle set,
-                         iBase_EntityType type,
-                         iMesh_EntityTopology topo,
-                         std::vector<iBase_EntityHandle>& entities )
-{
-  iBase_EntitySetHandle* array = 0;
-  int junk = 0, size = 0, err;
-  iMesh_getEntities( imesh, set, type, topo, &array, &junk, &size, &err );
-  if (!err) {
-    entities.clear();
-    entities.resize( size );
-    std::copy( array, array + size, entities.begin() );
-    free( array );
-  }
-  return err;
-}
-
-static int get_intersection( iMesh_Instance imesh,
-                             iBase_EntitySetHandle set1,
-                             iBase_EntitySetHandle set2,
-                             iBase_EntityType type,
-                             iMesh_EntityTopology topo,
-                             std::vector<iBase_EntityHandle>& entities )
-{
-  std::vector<iBase_EntityHandle> l1, l2;
-  int err;
-  err = get_entities( imesh, set1, type, topo, l1 );
-  if (err)
-    return err;
-  err = get_entities( imesh, set2, type, topo, l2 );
-  if (err)
-    return err;
   
-  std::sort( l1.begin(), l1.end() );
-  std::sort( l2.begin(), l2.end() );
-  std::set_intersection( l1.begin(), l1.end(),
-                         l2.begin(), l2.end(),
-                         std::back_inserter( entities ) );
-  return iBase_SUCCESS;
-}
 
-static int get_part_quads_and_verts( iMesh_Instance imesh,
-                                     iMeshP_PartHandle part,
-                                     std::vector<iBase_EntityHandle>& elems,
-                                     std::vector<iBase_EntityHandle>& verts )
-{
-  int ierr = get_entities( imesh, part, iBase_FACE, iMesh_QUADRILATERAL, elems );
-  CHKERR;
-  
-  verts.resize(4*elems.size());
-  std::vector<int> junk(elems.size()+1);
-  int junk1 = verts.size(), count, junk2 = junk.size(), junk3;
-  iBase_EntityHandle* junk4 = &verts[0];
-  int* junk5 = &junk[0];
-  iMesh_getEntArrAdj( imesh, &elems[0], elems.size(), iBase_VERTEX,
-                      &junk4, &junk1, &count,
-                      &junk5, &junk2, &junk3, &ierr );
-  CHKERR;
-  assert( junk1 == (int)verts.size() );
-  assert( count == (int)(4*elems.size()) );
-  assert( junk2 == (int)junk.size() );
-  assert( junk4 == &verts[0] );
-  assert( junk5 == &junk[0] );
-  std::sort( verts.begin(), verts.end() );
-  verts.erase( std::unique( verts.begin(), verts.end() ), verts.end() );
-  return iBase_SUCCESS;
-}
-  
-  
-
 /**************************************************************************
                            Test  Implementations
  **************************************************************************/
@@ -1285,14 +1311,9 @@
   assert(9 == num_vtx);
   
     // get vertex coords
-  double coords[27], *coord_ptr = coords;
-  junk1 = 27;
-  int storage = iBase_INTERLEAVED;
-  iMesh_getVtxArrCoords( imesh, conn, 9, &storage, &coord_ptr, &junk1, &junk2, &ierr );
+  std::vector<double> coords(27);
+  ierr = get_coords( imesh, conn, 9, &coords[0] );
   CHKERR;
-  assert( coord_ptr == coords );
-  assert( junk1 == 27 );
-  assert( junk2 == 27 );
   
     // use vertex coords to determine logical position
   for (int i = 0; i < num_vtx; ++i) {
@@ -1783,13 +1804,8 @@
     // for each vertex, store { (x << 2) | y, owning part id }
   std::vector<int> vtxdata( 2 * all_verts.size() );
   std::vector<double> coords( 3 * all_verts.size() );
-  double* junk7 = &coords[0];
-  junk1 = coords.size();
-  junk4 = iBase_INTERLEAVED;
-  iMesh_getVtxArrCoords( imesh, &all_verts[0], all_verts.size(), &junk4, &junk7, &junk1, &junk3, &ierr );
+  ierr = get_coords( imesh, &all_verts[0], all_verts.size(), &coords[0] );
   CHKERR;
-  assert(junk7 == &coords[0]);
-  assert(junk3 == (int)coords.size());
   for (size_t i = 0; i < all_verts.size(); ++i) {
     int x = (int)round(coords[3*i  ]);
     int y = (int)round(coords[3*i+1]);
@@ -1991,12 +2007,279 @@
  * Test:
  * - iMeshP_getNumCopies
  * - iMeshP_getCopyParts
+ */
+int test_entity_copy_parts( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
+{
+  int ierr, rank, size;
+  MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+  MPI_Comm_size( MPI_COMM_WORLD, &size );
+    
+    // get local part handles
+  std::vector<iMeshP_PartHandle> parts;
+  ierr = get_local_parts( imesh, prtn, parts );
+  PCHECK;
+  ASSERT( !parts.empty() );
+
+    // select a singe part to test
+  const iMeshP_PartHandle part = parts[0];
+  int logical_id;
+  ierr = map.part_from_coords( imesh, part, logical_id );
+  CHKERR;
+  const iMeshP_Part part_id = map.part_id_from_local_id( logical_id );
+  
+    // get vertices in part
+  std::vector<iBase_EntityHandle> quads, verts;
+  ierr = get_part_quads_and_verts( imesh, part, quads, verts );
+  PCHECK;
+  
+    // get neighbors
+  int neighbors[5], num_neighbors;
+  get_part_neighbors( logical_id, map.get_parts().size(), neighbors, num_neighbors );
+    
+    // build map of sharing data for each vertex
+  std::map< iBase_EntityHandle, std::vector<iMeshP_Part> > vert_sharing;
+  for (int j = 0; j < num_neighbors; ++j) {
+    iBase_EntityHandle iface[3];
+    int num_iface;
+    ierr = interface_verts( imesh, prtn, part, neighbors[j], map, iface, num_iface );
+    CHKERR;
+    for (int k = 0; k < num_iface; ++k)
+      vert_sharing[iface[k]].push_back( map.part_id_from_local_id( neighbors[j] ) );
+  }
+  
+    // test getNumCopies for each vertex
+  std::map< iBase_EntityHandle, std::vector<iMeshP_Part> >::iterator i;
+  int num_failed = 0, num_incorrect = 0;
+  for (i = vert_sharing.begin(); i != vert_sharing.end(); ++i) {
+    int count;
+    iBase_EntityHandle vtx = i->first;
+    iMeshP_getNumCopies( imesh, prtn, vtx, &count, &ierr );
+    if (ierr)
+      ++num_failed;
+    else if ((unsigned)count != i->second.size()+1) // add one for the part we queried from
+      ++num_incorrect;
+  }
+  ASSERT( 0 == num_failed );
+  ASSERT( 0 == num_incorrect );
+  
+    // get getCopyParts for each vertex
+  num_failed = num_incorrect = 0;
+  for (i = vert_sharing.begin(); i != vert_sharing.end(); ++i) {
+    iMeshP_Part* list = 0;
+    int junk = 0, count;
+    iMeshP_getCopyParts( imesh, prtn, i->first, &list, &junk, &count, &ierr );
+    if (iBase_SUCCESS != ierr) {
+      ++num_failed;
+      continue;
+    }
+    if ((unsigned)count != i->second.size()+1) { // add one for the part we queried from
+      ++num_incorrect;
+      free(list);
+      continue;
+    }
+    
+    std::vector<iMeshP_Part> expected( i->second );
+    expected.push_back( part_id );
+    std::sort( list, list+count );
+    std::sort( expected.begin(), expected.end() );
+    bool eq = std::equal( list, list+count, expected.begin() );
+    free( list );
+    if (!eq)
+      ++num_incorrect;
+  }
+  ASSERT( 0 == num_failed );
+  ASSERT( 0 == num_incorrect );
+  
+  return iBase_SUCCESS;
+}
+
+// store remote handle data for a vertex
+struct VtxCopyData {
+  std::vector<iMeshP_Part> parts;
+  std::vector<iBase_EntityHandle> handles;
+};
+
+/**\brief Test information about entity copies for interface entities
+ *
+ * Test:
  * - iMeshP_getCopies
  * - iMeshP_getCopyOnPart
  * - iMeshP_getOwnerCopy
  */
-int test_entity_copies( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& )
+int test_entity_copies( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
 {
+  int ierr, rank, size;
+  MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+  MPI_Comm_size( MPI_COMM_WORLD, &size );
+
+  // generate a unique ID for each vertex using the coordinates.
+  // see create_mesh(..): each vertex has integer coordinates (x,y,0)
+  //                      with x in [0,inf] and y in [0,4]
+  // then to an Allgatherv to exchange handles for each processor
+  
+  // cast everything to iBase_EntityHandle so we can pack it all in one communication
+  MPI_Datatype tmp_type;
+  if (sizeof(iBase_EntityHandle) == sizeof(unsigned))
+    tmp_type = MPI_UNSIGNED;
+  else if (sizeof(iBase_EntityHandle) == sizeof(unsigned long))
+    tmp_type = MPI_UNSIGNED_LONG;
+  else
+    return iBase_FAILURE;
+  const MPI_Datatype type = tmp_type; // make it const
+    
+    // get local part handles
+  std::vector<iMeshP_PartHandle> parts;
+  ierr = get_local_parts( imesh, prtn, parts );
+  PCHECK;
+  std::vector<iMeshP_Part> part_ids(parts.size());
+  iMeshP_Part* junk1 = &part_ids[0];
+  int junk2 = part_ids.size(), junk3;
+  iMeshP_getPartIdsFromPartHandlesArr( imesh, prtn, &parts[0], parts.size(),
+                                       &junk1, &junk2, &junk3, &ierr );
+  PCHECK;
+  assert( junk1 == &part_ids[0] );
+  assert( junk2 == (int)part_ids.size() );
+  assert( junk3 == (int)parts.size() );
+  
+    // build list of {vtx_id, part_id, handle} tuples to send
+    // also build list of local vertex handles
+  std::vector<iBase_EntityHandle> local_data, local_vertices;
+  for (size_t i = 0; i < parts.size(); ++i) {
+      // get vertices
+    std::vector<iBase_EntityHandle> quads, verts;
+    ierr = get_part_quads_and_verts( imesh, parts[i], quads, verts );
+    if (ierr)
+      break;
+    
+      // get vertex coodinates
+    std::vector<double> coords(3*verts.size());
+    ierr = get_coords( imesh, &verts[0], verts.size(), &coords[0] );
+    if (ierr)
+      break;
+    
+      // add all vertices to local_data
+    for (size_t j = 0; j < verts.size(); ++j) {
+      int xc = (int)round(coords[3*j  ]);
+      int yc = (int)round(coords[3*j+1]);
+      int tag = 5*xc + yc + 1;
+      local_data.push_back( (iBase_EntityHandle)tag );
+      local_data.push_back( (iBase_EntityHandle)part_ids[i] );
+      local_data.push_back( verts[j] );
+    }
+    
+    std::copy( verts.begin(), verts.end(), std::back_inserter(local_vertices) );
+  }
+  
+    // build list of local vertices
+  std::sort( local_vertices.begin(), local_vertices.end() );
+  local_vertices.erase( std::unique( local_vertices.begin(), local_vertices.end() ), local_vertices.end() );
+  std::vector<int> local_vtx_tags(local_vertices.size());
+  std::vector<double> local_coords(3*local_vertices.size());
+  ierr = get_coords( imesh, &local_vertices[0], local_vertices.size(), &local_coords[0] );
+  CHKERR;
+  for (size_t i = 0; i < local_vertices.size(); ++i) {
+    int xc = (int)round(local_coords[3*i  ]);
+    int yc = (int)round(local_coords[3*i+1]);
+    local_vtx_tags[i] = 5*xc + yc + 1;
+  }
+  
+    // communicate data
+  std::vector<int> gcounts(size), gdisp(size);
+  int local_data_size = local_data.size();
+  ierr = MPI_Allgather( &local_data_size, 1, MPI_INT, &gcounts[0], 1, MPI_INT, MPI_COMM_WORLD );
+  CHKERR;
+  gdisp[0] = 0;
+  for (int i = 1; i < size; ++i)
+    gdisp[i] = gdisp[i-1]+gcounts[i-1];
+  std::vector<iBase_EntityHandle> global_data( gdisp[size-1]+gcounts[size-1] );
+  ierr = MPI_Allgatherv( &local_data[0], local_data_size, type, 
+                         &global_data[0], &gcounts[0], &gdisp[0], type, MPI_COMM_WORLD );
+  CHKERR;
+  
+    // arrange global data in a more useful way
+  std::map<int,VtxCopyData> vtx_sharing;
+  assert( global_data.size() % 3 == 0 );
+  for (size_t i = 0; i < global_data.size(); i += 3) {
+    int tag =                  (int)(size_t)global_data[i  ];
+    iMeshP_Part part = (iMeshP_Part)(size_t)global_data[i+1];
+    iBase_EntityHandle handle =             global_data[i+2];
+    vtx_sharing[tag].parts.push_back( part );
+    vtx_sharing[tag].handles.push_back( handle );
+  }
+  
+    // test iMeshP_getCopies for each local vertex
+  int num_error = 0, num_incorrect = 0, junk4;
+  for (size_t i = 0; i < local_vertices.size(); ++i) {
+    int num_copies = -1;
+    iMeshP_Part* part_ids = 0;
+    iBase_EntityHandle* copies = 0;
+    junk2 = junk3 = junk4 = 0;
+    iMeshP_getCopies( imesh, prtn, local_vertices[i],
+                      &part_ids, &junk2, &num_copies, 
+                      &copies, &junk3, &junk4, &ierr );
+    if (iBase_SUCCESS != ierr) {
+      ++num_error;
+      continue;
+    }
+    assert( junk4 == num_copies );
+    
+    VtxCopyData& expected = vtx_sharing[local_vtx_tags[i]];
+    if (num_copies != (int)expected.parts.size())
+      ++num_incorrect;
+    else for (size_t j = 0; j < expected.parts.size(); ++j) {
+      int idx = std::find( part_ids, part_ids+num_copies, expected.parts[j] ) - part_ids;
+      if (idx == num_copies || copies[idx] != expected.handles[j]) {
+        ++num_incorrect;
+        break;
+      }
+    }
+    free(part_ids);
+    free(copies);
+  }
+  ASSERT( 0 == num_error );
+  ASSERT( 0 == num_incorrect );
+   
+    // test iMeshP_getCopyOnPart for each local vertex
+  num_error = num_incorrect = 0;
+  for (size_t i = 0; i < local_vertices.size(); ++i) {
+    VtxCopyData& expected = vtx_sharing[local_vtx_tags[i]];
+    for (size_t j = 0; j < expected.parts.size(); ++j) {
+      iBase_EntityHandle copy;
+      iMeshP_getCopyOnPart( imesh, prtn, local_vertices[i], expected.parts[j], &copy, &ierr );
+      if (iBase_SUCCESS != ierr)
+        ++num_error;
+      else if (expected.handles[j] != copy)
+        ++num_incorrect;
+    }
+  }
+  ASSERT( 0 == num_error );
+  ASSERT( 0 == num_incorrect );
+
+    // test iMeshP_getOwnerCopy for each local vertex
+  num_error = num_incorrect = 0;
+  for (size_t i = 0; i < local_vertices.size(); ++i) {
+    VtxCopyData& expected = vtx_sharing[local_vtx_tags[i]];
+    iMeshP_Part owner_id = 0;
+    iMeshP_getEntOwnerPart( imesh, prtn, local_vertices[i], &owner_id, &ierr );
+    if (iBase_SUCCESS != ierr) 
+      continue; // not testing getEntOwnerPart here
+    
+    size_t idx = std::find( expected.parts.begin(), expected.parts.end(), owner_id )
+                   - expected.parts.begin();
+    if (idx == expected.parts.size())
+      continue; // not testing getEntOwnerPart here
+    
+    iMeshP_Part owner_id_2 = 0;
+    iBase_EntityHandle copy = 0;
+    iMeshP_getOwnerCopy( imesh, prtn, local_vertices[i], &owner_id_2, &copy, &ierr );
+    if (iBase_SUCCESS != ierr)
+      ++num_error;
+    else if (owner_id_2 != owner_id && copy != expected.handles[idx])
+      ++num_incorrect;
+  }
+  ASSERT( 0 == num_error );
+  ASSERT( 0 == num_incorrect );
+  
   return iBase_SUCCESS;
 }
 




More information about the moab-dev mailing list