[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