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

kraftche at mcs.anl.gov kraftche at mcs.anl.gov
Sat Nov 15 03:37:07 CST 2008


Author: kraftche
Date: 2008-11-15 03:37:07 -0600 (Sat, 15 Nov 2008)
New Revision: 2264

Modified:
   MOAB/trunk/tools/iMesh/iMeshP_unit_tests.cpp
Log:
o Fix bugs when tests are run with an odd number of processors other than 1.
o Test iMeshP_getNumPartBdryEnts and iMeshP_getPartBdryEnts with iMeshP_ALL_PARTS
o Implement test for iMeshP_createGhostEntsAll
o Move testing of iMeshP_pushTags and iMeshP_pushTagsEnt before
  testing iMeshP_createGhostEntsAll, otherwise they fail due to
  messed up sharing data for ghosted entities (see failing test
  in parallel/parallel_unit_tests.cpp).


Modified: MOAB/trunk/tools/iMesh/iMeshP_unit_tests.cpp
===================================================================
--- MOAB/trunk/tools/iMesh/iMeshP_unit_tests.cpp	2008-11-15 09:32:05 UTC (rev 2263)
+++ MOAB/trunk/tools/iMesh/iMeshP_unit_tests.cpp	2008-11-15 09:37:07 UTC (rev 2264)
@@ -197,8 +197,7 @@
 /**\brief Test creation of ghost entities
  *
  * Test:
- * - iMeshP_addGhostOf
- * - iMeshP_createGhostEnts
+ * - iMeshP_createGhostEntsAll
  */
 int test_create_ghost_ents( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
 
@@ -270,6 +269,9 @@
 /**\brief Create mesh for use in parallel tests */
 int create_mesh( const char* filename, int num_parts );
 
+/**\brief get unique identifier for each vertex */
+int vertex_tag( iMesh_Instance imesh, iBase_EntityHandle vertex, int& tag );
+
 int get_local_parts( iMesh_Instance instance,
                      iMeshP_PartitionHandle prtn,
                      std::vector<iMeshP_PartHandle>& handles,
@@ -411,10 +413,6 @@
   return is_err;
 }
 
-/**\brief Create mesh for use in parallel tests */
-int create_mesh( const char* filename, int num_parts );
-
-
 int main( int argc, char* argv[] )
 {
   MPI_Init(&argc, &argv);
@@ -429,7 +427,7 @@
 #endif
       // loop forever on requested processor, giving the user time
       // to attach a debugger.  Once the debugger in attached, user
-      // can change 'stop'.  E.g. on gdb do "set var pause = 0"
+      // can change 'pause'.  E.g. on gdb do "set var pause = 0"
     if (atoi(argv[2]) == rank) {
       volatile int pause = 1;
       while (pause);
@@ -483,8 +481,8 @@
   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_push_tag_data );
   num_errors += RUN_TEST( test_create_ghost_ents );
-  num_errors += RUN_TEST( test_push_tag_data );
   
     // wait until all procs are done before writing summary data
   std::cout.flush();
@@ -556,7 +554,7 @@
   const int num_full_cols = 2 * (num_parts / 2);
   const int need_half_cols = num_parts % 2;
   const int num_cols = num_full_cols + 2*need_half_cols;
-  const int num_vtx = 5+5*num_cols - 6*(num_parts%2);
+  const int num_vtx = 5+5*num_cols - 4*(num_parts%2);
   std::vector< EHARR<5> > vertices( num_cols + 1 );
   std::vector< EHARR<4> > elements( num_cols );
   std::vector<int> vertex_ids( num_vtx );
@@ -573,7 +571,7 @@
                           i, 3, 0,
                           i, 4, 0 };
     iBase_EntityHandle* ptr = vertices[i];
-    const int n = (num_full_cols && i <= num_full_cols) ? 5 : 3;
+    const int n = (num_full_cols == num_cols || i <= num_full_cols) ? 5 : 3;
     int junk1 = n, junk2 = n;
     iMesh_createVtxArr( imesh, n, iBase_INTERLEAVED, coords, 3*n,
                         &ptr, &junk1, &junk2, &ierr ); CHKERR;
@@ -658,7 +656,22 @@
   
   return 0;
 }
+
+// generate unique for each vertex from coordinates.
+// Assume integer coordinate values with x in [0,inf] and y in [0,4]
+// as generated by create_mean(..).
+int vertex_tag( iMesh_Instance imesh, iBase_EntityHandle vertex, int& tag ) 
+{
+  int ierr;
+  double x, y, z;
+  iMesh_getVtxCoord( imesh, vertex, &x, &y, &z, &ierr );
+  CHKERR;
   
+  int xc = (int)round(x);
+  int yc = (int)round(y);
+  tag = 5*xc + yc + 1;
+  return ierr;
+}
 
 /**************************************************************************
                            Test  Implementations
@@ -764,7 +777,7 @@
     // from number of parts (see create_mesh(..) function.)
   const int expected_global_quad_count = 4 * num_parts;
   const int num_col = 2 * (num_parts / 2 + num_parts % 2);
-  const int expected_global_vtx_count = 5 + 5*num_col - 6*(num_parts % 2);
+  const int expected_global_vtx_count = 5 + 5*num_col - 4*(num_parts % 2);
   
     // test getNumOf*All for root set
   int ierr, count;
@@ -1414,6 +1427,7 @@
   std::vector<iMeshP_PartHandle> local_handles;
   std::vector<iMeshP_Part> local_ids;
   std::vector<iMeshP_Part> all_parts = map.get_parts();
+  std::map< iMeshP_PartHandle, std::vector<iBase_EntityHandle> > part_bdry;
   ierr = get_local_parts( imesh, prtn, local_handles, &local_ids );
   CHKERR;
   
@@ -1459,6 +1473,7 @@
       if (iBase_SUCCESS != ierr)
         list_error.push_back( part_pair );
       else {
+        std::copy( ptr, ptr + count, std::back_inserter( part_bdry[local_handles[i]] ) );
         std::sort( ptr, ptr + count );
         if (num_shared_verts != count ||
             !std::equal( shared_verts, shared_verts + num_shared_verts, ptr ))
@@ -1493,6 +1508,62 @@
               << "  iMeshP_getPartBdryEnts return incorrect results for " << list_failed.size() << " part pairs." << std::endl;
     ierr = iBase_FAILURE;
   }
+  
+  if (iBase_SUCCESS != ierr)
+    return ierr;
+  
+  
+    // test with iMeshP_ALL_PARTS
+  for (size_t i = 0; i < local_handles.size(); ++i) {
+    std::vector<iBase_EntityHandle>& exp_bdry = part_bdry[local_handles[i]];
+    std::sort( exp_bdry.begin(), exp_bdry.end() );
+    exp_bdry.erase( std::unique( exp_bdry.begin(), exp_bdry.end() ), exp_bdry.end() );
+    std::pair<iMeshP_Part,iMeshP_Part> part_pair;
+    part_pair.first = local_ids[i];
+    part_pair.second = iMeshP_ALL_PARTS; 
+    
+    int num = 0;
+    iMeshP_getNumPartBdryEnts( imesh, prtn, local_handles[i], iBase_VERTEX, iMesh_POINT, 
+                               iMeshP_ALL_PARTS, &num, &ierr );
+    if (ierr)
+      num_error.push_back( part_pair );
+    else if (num != (int)exp_bdry.size())
+      num_failed.push_back( part_pair );
+      
+    iBase_EntityHandle* bdry = 0;
+    int junk = num = 0;
+    iMeshP_getPartBdryEnts( imesh, prtn, local_handles[i], iBase_VERTEX, iMesh_POINT,
+                            iMeshP_ALL_PARTS, &bdry, &junk, &num, &ierr );
+    if (ierr)
+      list_error.push_back( part_pair );
+    else {
+      std::sort( bdry, bdry+num );
+      if (num != (int)exp_bdry.size() || !std::equal( bdry, bdry+num, exp_bdry.begin() ))
+        list_failed.push_back( part_pair );
+      free(bdry);
+    }
+  }  
+  if (!num_error.empty()) {
+    std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
+              << "  iMeshP_getNumPartBdryEnts return error for " << num_error.size() << " part pairs." << std::endl;
+    ierr = iBase_FAILURE;
+  }
+  if (!list_error.empty()) {
+    std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
+              << "  iMeshP_getPartBdryEnts return error for " << list_error.size() << " part pairs." << std::endl;
+    ierr = iBase_FAILURE;
+  }
+  if (!num_failed.empty()) {
+    std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
+              << "  iMeshP_getNumPartBdryEnts return incorrect results for " << num_failed.size() << " part pairs." << std::endl;
+    ierr = iBase_FAILURE;
+  }
+  if (!list_failed.empty()) {
+    std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
+              << "  iMeshP_getPartBdryEnts return incorrect results for " << list_failed.size() << " part pairs." << std::endl;
+    ierr = iBase_FAILURE;
+  }
+  
   return ierr;
 }
 
@@ -2151,22 +2222,19 @@
     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;
+      int tag;
+      ierr = vertex_tag( imesh, verts[j], tag );
+      if (ierr)
+        break;
       local_data.push_back( (iBase_EntityHandle)tag );
       local_data.push_back( (iBase_EntityHandle)part_ids[i] );
       local_data.push_back( verts[j] );
     }
-    
+    if (ierr)
+      break;
+      
     std::copy( verts.begin(), verts.end(), std::back_inserter(local_vertices) );
   }
   
@@ -2174,14 +2242,13 @@
   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;
+    ierr = vertex_tag( imesh, local_vertices[i], local_vtx_tags[i] );
+    if (ierr)
+      break;
   }
+  CHKERR;
   
     // communicate data
   std::vector<int> gcounts(size), gdisp(size);
@@ -2283,16 +2350,192 @@
   return iBase_SUCCESS;
 }
 
+
+int get_num_adj_quads( iMesh_Instance imesh, iBase_EntityHandle vtx, int& num )
+{
+  iBase_EntityHandle* list = 0;
+  int ierr, junk = 0;
+  iMesh_getEntAdj( imesh, vtx, iBase_FACE, &list, &junk, &num, &ierr );
+  if (iBase_SUCCESS == ierr)
+    free(list);
+  return ierr;
+}
+
+int get_adj( iMesh_Instance imesh, 
+             iBase_EntityHandle ent, 
+             int type,
+             std::vector<iBase_EntityHandle>& adj )
+{
+  iBase_EntityHandle* list = 0;
+  int ierr, num, junk = 0;
+  iMesh_getEntAdj( imesh, ent, type, &list, &junk, &num, &ierr );
+  if (iBase_SUCCESS == ierr) {
+    std::copy( list, list+num, std::back_inserter(adj) );
+    free( list );
+  }
+  return ierr;
+}
+
+// assume regular quad mesh
+int get_boundary_vertices( iMesh_Instance imesh, std::vector<iBase_EntityHandle>& bdry )
+{
+  int ierr, n;
+  iBase_EntitySetHandle root;
+  iMesh_getRootSet( imesh, &root, &ierr );
+  CHKERR;
+  std::vector<iBase_EntityHandle> all_verts;
+  ierr = get_entities( imesh, root, iBase_VERTEX, iMesh_POINT, all_verts );
+  CHKERR;
+  bdry.clear();
+  for (size_t i = 0; i < all_verts.size(); ++i) {
+    ierr = get_num_adj_quads( imesh, all_verts[i], n );
+    CHKERR;
+    if (n != 4)
+      bdry.push_back( all_verts[i] );
+  }
+  return iBase_SUCCESS;
+}
+
+int check_one_layer( iMesh_Instance imesh, iBase_EntityHandle vtx,
+                     const std::vector<iBase_EntityHandle>& sorted_vertices )
+{
+  int ierr;
+  if (std::binary_search( sorted_vertices.begin(), sorted_vertices.end(), vtx ))
+    return iBase_SUCCESS;
+  std::vector<iBase_EntityHandle> quads, verts;
+  ierr = get_adj( imesh, vtx, iBase_FACE, quads );
+  CHKERR;
+  for (size_t i = 0; i < quads.size(); ++i) {
+    verts.clear();
+    ierr = get_adj( imesh, quads[i], iBase_VERTEX, verts );
+    CHKERR;
+    for (size_t j = 0; j < verts.size(); ++j) {
+      if (std::binary_search( sorted_vertices.begin(), sorted_vertices.end(), verts[j] ))
+        return iBase_SUCCESS;
+    }
+  }
+  
+  return iBase_FAILURE;
+}
+  
+// get number of adjacent quads to each vertex, both on the local
+// processor and in the entire mesh
+int get_num_adj_all( iMesh_Instance imesh, 
+                     const std::vector<iBase_EntityHandle>& verts,
+                     std::vector<int>& num_local_adj,
+                     std::vector<int>& num_all_adj )
+{
+  int ierr, size;
+  MPI_Comm_size( MPI_COMM_WORLD, &size );
+
+  std::vector<int> vtx_tags(verts.size());
+  num_local_adj.resize( verts.size() );
+  for (size_t i = 0; i < verts.size(); ++i) {
+    ierr = get_num_adj_quads( imesh, verts[i], num_local_adj[i] );
+    CHKERR;
+    ierr = vertex_tag( imesh, verts[i], vtx_tags[i] );
+    CHKERR;
+  }
+  
+  std::vector<int> counts(size), displ(size);
+  int num_vtx = verts.size();
+  ierr = MPI_Allgather( &num_vtx, 1, MPI_INT, &counts[0], 1, MPI_INT, MPI_COMM_WORLD );
+  CHKERR;
+  displ[0] = 0;
+  for (int i = 1; i < size; ++i)
+    displ[i] = displ[i-1]+counts[i-1];
+  int total = displ[size-1]+counts[size-1];
+  std::vector<int> all_tags(total), all_adj_counts(total);
+  ierr = MPI_Allgatherv( &vtx_tags[0], vtx_tags.size(), MPI_INT, &all_tags[0], &counts[0], &displ[0], MPI_INT, MPI_COMM_WORLD );
+  CHKERR;
+  ierr = MPI_Allgatherv( &num_local_adj[0], num_local_adj.size(), MPI_INT, &all_adj_counts[0], &counts[0], &displ[0], MPI_INT, MPI_COMM_WORLD );
+  CHKERR;
+  
+  num_all_adj.clear();
+  num_all_adj.resize(total,0);
+  for (int i = 0; i < total; ++i) {
+    std::vector<int>::iterator it = std::find( vtx_tags.begin(), vtx_tags.end(), all_tags[i] );
+    if (it == vtx_tags.end())
+      continue;
+    int idx = it - vtx_tags.begin();
+    num_all_adj[idx] += all_adj_counts[i];
+  }
+  
+  return iBase_SUCCESS;
+}
+
+
 /**\brief Test creation of ghost entities
  *
  * Test:
- * - iMeshP_addGhostOf
- * - iMeshP_createGhostEnts
+ * - iMeshP_createGhostEntsAll
  */
-int test_create_ghost_ents( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& )
+int test_create_ghost_ents( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
 {
+  int ierr;
+  
+    // get boundary vertices
+  std::vector<iBase_EntityHandle> bdry;
+  ierr = get_boundary_vertices( imesh, bdry );
+  PCHECK;
+    // get counts of adjacent entities
+  std::vector<int> num_local_adj, num_global_adj;
+  ierr = get_num_adj_all( imesh, bdry, num_local_adj, num_global_adj );
+  PCHECK;
+    // create one layer of ghost entities
+  iMeshP_createGhostEntsAll( imesh, prtn, iBase_FACE, iBase_VERTEX, 1, 0, &ierr );
+  PCHECK;
+    // check that each vertex has the correct number of adjacent entities
+  int num_incorrect = 0;
+  for (size_t i = 0; i < bdry.size(); ++i) {
+    int n;
+    ierr = get_num_adj_quads( imesh, bdry[i], n );
+    if (iBase_SUCCESS != ierr || num_global_adj[i] != n)
+      ++num_incorrect;
+  }
+  ASSERT( 0 == num_incorrect );
+    // get new the new boundary
+  std::vector<iBase_EntityHandle> new_bdry;
+  ierr = get_boundary_vertices( imesh, new_bdry );
+  PCHECK;
+    // check that each vertex on the new boundary is separated by
+    // at most one layer from the old boundary
+  std::sort( bdry.begin(), bdry.end() );
+  num_incorrect = 0;
+  for (size_t i = 0; i < new_bdry.size(); ++i) {
+    ierr = check_one_layer( imesh, new_bdry[i], bdry );
+    if (ierr) 
+      ++num_incorrect;
+  }
+  ASSERT( 0 == num_incorrect );
+    // make another layer of ghost entiites
+  bdry.swap( new_bdry );
+  new_bdry.clear();
+  ierr = get_num_adj_all( imesh, bdry, num_local_adj, num_global_adj );
+  PCHECK;
+  iMeshP_createGhostEntsAll( imesh, prtn, iBase_FACE, iBase_VERTEX, 2, 0, &ierr );
+  PCHECK;
+    // check that each vertex has the correct number of adjacent entities
+  num_incorrect = 0;
+  for (size_t i = 0; i < bdry.size(); ++i) {
+    int n;
+    ierr = get_num_adj_quads( imesh, bdry[i], n );
+    if (iBase_SUCCESS != ierr || num_global_adj[i] != n)
+      ++num_incorrect;
+  }
+    // check that each vertex on the new boundary is separated by
+    // at most one layer from the old boundary
+  std::sort( bdry.begin(), bdry.end() );
+  num_incorrect = 0;
+  for (size_t i = 0; i < new_bdry.size(); ++i) {
+    ierr = check_one_layer( imesh, new_bdry[i], bdry );
+    if (ierr) 
+      ++num_incorrect;
+  }
+  ASSERT( 0 == num_incorrect );
+  
   return iBase_SUCCESS;
-}
+}  
 
 /**\brief Test commuinication of tag data
  *
@@ -2363,7 +2606,7 @@
   
     // test iMeshP_pushTagsEnt
     // write -1 on all vertices
-    // For each vertex owned by this processor and shared with more than,
+    // For each vertex owned by this processor and shared with more than
     // two others, write the rank of the owning processor.
   
   tag_vals.clear();




More information about the moab-dev mailing list