|
Sierra Toolkit
Version of the Day
|
00001 /*------------------------------------------------------------------------*/ 00002 /* Copyright 2010 Sandia Corporation. */ 00003 /* Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive */ 00004 /* license for use of this work by or on behalf of the U.S. Government. */ 00005 /* Export of this program may require a license from the */ 00006 /* United States Government. */ 00007 /*------------------------------------------------------------------------*/ 00008 00009 #include <iostream> 00010 #include <sstream> 00011 00012 #include <stk_util/unit_test_support/stk_utest_macros.hpp> 00013 00014 #include <stk_util/parallel/Parallel.hpp> 00015 00016 #include <stk_mesh/base/BulkData.hpp> 00017 #include <stk_mesh/base/GetEntities.hpp> 00018 #include <stk_mesh/base/Comm.hpp> 00019 00020 #include <stk_mesh/fixtures/RingFixture.hpp> 00021 00022 #include <unit_tests/UnitTestModificationEndWrapper.hpp> 00023 00024 using stk_classic::mesh::Part; 00025 using stk_classic::mesh::MetaData; 00026 using stk_classic::mesh::fem::FEMMetaData; 00027 using stk_classic::mesh::BulkData; 00028 using stk_classic::mesh::Entity; 00029 using stk_classic::mesh::Selector; 00030 using stk_classic::mesh::PartVector; 00031 using stk_classic::mesh::fixtures::RingFixture; 00032 00033 //---------------------------------------------------------------------- 00034 00035 STKUNIT_UNIT_TEST(UnitTestingOfBulkData, testChangeParts) 00036 { 00037 // This unit test tests part operations and verifies operations 00038 // by looking at bucket supersets. We use contrived entities 00039 // (as opposed to a fixture) for simplicity and clarity. 00040 00041 stk_classic::ParallelMachine pm = MPI_COMM_WORLD; 00042 MPI_Barrier( pm ); 00043 00044 const unsigned p_size = stk_classic::parallel_machine_size( pm ); 00045 const unsigned p_rank = stk_classic::parallel_machine_rank( pm ); 00046 00047 // Single process, no sharing 00048 00049 // Meta data with entity ranks [0..9] 00050 const unsigned spatial_dimension = 10; 00051 std::vector<std::string> entity_names(spatial_dimension+1); 00052 for ( size_t i = 0 ; i <= spatial_dimension ; ++i ) { 00053 std::ostringstream name ; 00054 name << "EntityRank_" << i ; 00055 entity_names[i] = name.str(); 00056 } 00057 00058 // Create a mesh with a bunch of parts 00059 00060 FEMMetaData meta( spatial_dimension, entity_names ); 00061 BulkData bulk( FEMMetaData::get_meta_data(meta) , pm , 100 ); 00062 00063 Part & part_univ = meta.universal_part(); 00064 Part & part_owns = meta.locally_owned_part(); 00065 Part & part_shared = meta.globally_shared_part(); 00066 00067 Part & part_A_0 = meta.declare_part(std::string("A_0"), 0 /*entity_rank*/); 00068 Part & part_A_1 = meta.declare_part(std::string("A_1"), 1 /*entity_rank*/); 00069 Part & part_A_2 = meta.declare_part(std::string("A_2"), 2 /*entity_rank*/); 00070 Part & part_A_3 = meta.declare_part(std::string("A_3"), 3 /*entity_rank*/); 00071 00072 Part & part_B_0 = meta.declare_part(std::string("B_0"), 0 /*entity_rank*/); 00073 Part & part_B_2 = meta.declare_part(std::string("B_2"), 2 /*entity_rank*/); 00074 00075 meta.commit(); 00076 bulk.modification_begin(); 00077 00078 PartVector tmp(1), no_parts; 00079 00080 // Declare a few entities of various ranks. In order for the sharing 00081 // to work, we need to have all the entities we'll be playing with 00082 // to be in the owned-closure of a high-level non-shared entity, we'll 00083 // call that entity the closure_entity because all the other entities 00084 // will be in it's closure. 00085 00086 Entity& closure_entity = bulk.declare_entity(4 /*entity rank*/, 00087 p_rank+1 /*id*/, 00088 no_parts); 00089 00090 tmp[0] = & part_A_0 ; 00091 Entity& entity_0_1 = bulk.declare_entity(0 /*entity rank*/, 1 /*id*/, tmp); 00092 bulk.declare_relation( closure_entity , entity_0_1 , 0 /*local_rel_id*/ ); 00093 00094 tmp[0] = & part_A_1 ; 00095 Entity& entity_1_1 = bulk.declare_entity(1 /*entity rank*/, 1 /*id*/, tmp); 00096 bulk.declare_relation( closure_entity , entity_1_1 , 1 /*local_rel_id*/ ); 00097 00098 tmp[0] = & part_A_2 ; 00099 Entity& entity_2_1 = bulk.declare_entity(2 /*entity rank*/, 1 /*id*/, tmp); 00100 bulk.declare_relation( closure_entity , entity_2_1 , 2 /*local_rel_id*/ ); 00101 00102 tmp[0] = & part_A_3 ; 00103 Entity& entity_3_1 = bulk.declare_entity(3 /*entity rank*/, 1 /*id*/, tmp); 00104 bulk.declare_relation( closure_entity , entity_3_1 , 3 /*local_rel_id*/ ); 00105 00106 // Ensure that the supersets of the buckets containing the entities we 00107 // just created are correct. 00108 00109 entity_0_1.bucket().supersets( tmp ); 00110 STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() ); 00111 STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) ); 00112 STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) ); 00113 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) ); 00114 00115 entity_1_1.bucket().supersets( tmp ); 00116 STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() ); 00117 STKUNIT_ASSERT( entity_1_1.bucket().member(part_univ) ); 00118 STKUNIT_ASSERT( entity_1_1.bucket().member(part_owns) ); 00119 STKUNIT_ASSERT( entity_1_1.bucket().member(part_A_1) ); 00120 00121 entity_2_1.bucket().supersets( tmp ); 00122 STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() ); 00123 STKUNIT_ASSERT( entity_2_1.bucket().member(part_univ) ); 00124 STKUNIT_ASSERT( entity_2_1.bucket().member(part_owns) ); 00125 STKUNIT_ASSERT( entity_2_1.bucket().member(part_A_2) ); 00126 00127 entity_3_1.bucket().supersets( tmp ); 00128 STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() ); 00129 STKUNIT_ASSERT( entity_3_1.bucket().member(part_univ) ); 00130 STKUNIT_ASSERT( entity_3_1.bucket().member(part_owns) ); 00131 STKUNIT_ASSERT( entity_3_1.bucket().member(part_A_3) ); 00132 00133 // Add entity_0_1 to the part it was already in 00134 { 00135 tmp.resize(1); 00136 tmp[0] = & part_A_0 ; 00137 bulk.change_entity_parts( entity_0_1 , tmp ); 00138 entity_0_1.bucket().supersets( tmp ); 00139 STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() ); 00140 STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) ); 00141 STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) ); 00142 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) ); 00143 } 00144 00145 // Add entity_0_1 to part_B_0 00146 { 00147 tmp.resize(1); 00148 tmp[0] = & part_B_0 ; 00149 bulk.change_entity_parts( entity_0_1 , tmp ); 00150 entity_0_1.bucket().supersets( tmp ); 00151 STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() ); 00152 STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) ); 00153 STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) ); 00154 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) ); 00155 STKUNIT_ASSERT( entity_0_1.bucket().member(part_B_0) ); 00156 } 00157 00158 // Remove entity_0_1 from the part it was just added to above 00159 { 00160 tmp.resize(1); 00161 tmp[0] = & part_B_0 ; 00162 bulk.change_entity_parts( entity_0_1 , PartVector() , tmp ); 00163 entity_0_1.bucket().supersets( tmp ); 00164 STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() ); 00165 STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) ); 00166 STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) ); 00167 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) ); 00168 } 00169 00170 // Add relation from entity_1_1 (which is in part_A_1) to 00171 // entity_0_1 (which is in part_A_0). After the relation 00172 // is added, there is an induced membership of entity_0_1 00173 // within part A_1. 00174 stk_classic::mesh::RelationIdentifier test_rel_id = 0; 00175 { 00176 bulk.declare_relation( entity_1_1 , entity_0_1 , test_rel_id ); 00177 entity_0_1.bucket().supersets( tmp ); 00178 STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() ); 00179 STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) ); 00180 STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) ); 00181 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) ); 00182 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_1) ); 00183 } 00184 00185 // Remove the relationship added in the step above and 00186 // demonstrate that the induced membership of entity_0_1 00187 // in part_A_1 is gone 00188 { 00189 bulk.destroy_relation( entity_1_1 , entity_0_1, test_rel_id ); 00190 entity_0_1.bucket().supersets( tmp ); 00191 STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() ); 00192 STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) ); 00193 STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) ); 00194 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) ); 00195 } 00196 00197 // Add entity_2_1 to part_B_2 00198 { 00199 tmp.resize(1); 00200 tmp[0] = & part_B_2 ; 00201 bulk.change_entity_parts( entity_2_1 , tmp ); 00202 entity_2_1.bucket().supersets( tmp ); 00203 STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() ); 00204 STKUNIT_ASSERT( entity_2_1.bucket().member(part_univ) ); 00205 STKUNIT_ASSERT( entity_2_1.bucket().member(part_owns) ); 00206 STKUNIT_ASSERT( entity_2_1.bucket().member(part_A_2) ); 00207 STKUNIT_ASSERT( entity_2_1.bucket().member(part_B_2) ); 00208 } 00209 00210 // Add relation from entity_2_1 (which is in part_A_2 and B_2) to 00211 // entity_0_1 (which is in part_A_0). After the relation 00212 // is added, there is an induced membership of entity_0_1 00213 // within entity_2_1's parts (A_2 and B_2) (and of course entity_0_1 00214 // is still in the parts it was already in). 00215 { 00216 bulk.declare_relation( entity_2_1 , entity_0_1 , test_rel_id ); 00217 entity_0_1.bucket().supersets( tmp ); 00218 STKUNIT_ASSERT_EQUAL( size_t(5) , tmp.size() ); 00219 STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) ); 00220 STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) ); 00221 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) ); 00222 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_2) ); 00223 STKUNIT_ASSERT( entity_0_1.bucket().member(part_B_2) ); 00224 } 00225 00226 // Remove the relationship added in the step above and 00227 // demonstrate that the induced membership of entity_0_1 00228 // in parts A_2 and B_2 is gone. 00229 { 00230 bulk.destroy_relation( entity_2_1 , entity_0_1, test_rel_id ); 00231 entity_0_1.bucket().supersets( tmp ); 00232 STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() ); 00233 STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) ); 00234 STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) ); 00235 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) ); 00236 } 00237 00238 bulk.modification_end(); 00239 00240 //------------------------------ 00241 // Now the parallel fun. Existing entities should be shared 00242 // by all processes since they have the same identifiers. 00243 // They should also have the same parts. 00244 00245 bool parallel = p_size > 1; 00246 00247 // For parallel runs, the entities should be in the same parts 00248 // as they were before the modification end and they should 00249 // be in the shared part as well. 00250 00251 entity_0_1.bucket().supersets( tmp ); 00252 if ( entity_0_1.owner_rank() == p_rank ) { 00253 STKUNIT_ASSERT_EQUAL( size_t(parallel ? 4 : 3) , tmp.size() ); 00254 STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) ); 00255 STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) ); 00256 if ( parallel ) 00257 STKUNIT_ASSERT( entity_0_1.bucket().member(part_shared) ); 00258 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) ); 00259 } 00260 else { 00261 STKUNIT_ASSERT( parallel ); 00262 STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() ); 00263 STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) ); 00264 STKUNIT_ASSERT( entity_0_1.bucket().member(part_shared) ); 00265 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) ); 00266 } 00267 00268 entity_2_1.bucket().supersets( tmp ); 00269 if ( entity_2_1.owner_rank() == p_rank ) { 00270 STKUNIT_ASSERT_EQUAL( size_t(parallel ? 5 : 4) , tmp.size() ); 00271 STKUNIT_ASSERT( entity_2_1.bucket().member(part_univ) ); 00272 STKUNIT_ASSERT( entity_2_1.bucket().member(part_owns) ); 00273 if ( parallel ) 00274 STKUNIT_ASSERT( entity_2_1.bucket().member(part_shared) ); 00275 STKUNIT_ASSERT( entity_2_1.bucket().member(part_A_2) ); 00276 STKUNIT_ASSERT( entity_2_1.bucket().member(part_B_2) ); 00277 } 00278 else { 00279 STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() ); 00280 STKUNIT_ASSERT( entity_2_1.bucket().member(part_univ) ); 00281 STKUNIT_ASSERT( entity_2_1.bucket().member(part_shared) ); 00282 STKUNIT_ASSERT( entity_2_1.bucket().member(part_A_2) ); 00283 STKUNIT_ASSERT( entity_2_1.bucket().member(part_B_2) ); 00284 } 00285 00286 if ( parallel ) { 00287 // If parallel, check that the entities are shared across all procs. 00288 STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_0_1.sharing().size() ); 00289 STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_1_1.sharing().size() ); 00290 STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_2_1.sharing().size() ); 00291 STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_3_1.sharing().size() ); 00292 } 00293 00294 bulk.modification_begin(); 00295 00296 // Add entity_0_1 to a new part on the owning process 00297 00298 int ok_to_modify = entity_0_1.owner_rank() == p_rank ; 00299 00300 try { 00301 tmp.resize(1); 00302 tmp[0] = & part_B_0 ; 00303 bulk.change_entity_parts( entity_0_1 , tmp ); 00304 STKUNIT_ASSERT( ok_to_modify ); 00305 } 00306 catch( const std::exception & x ) { 00307 STKUNIT_ASSERT( ! ok_to_modify ); 00308 } 00309 00310 // Check that entity_0_1 is in the new part on the owning 00311 // process, but not on other processes. 00312 00313 entity_0_1.bucket().supersets( tmp ); 00314 if ( entity_0_1.owner_rank() == p_rank ) { 00315 STKUNIT_ASSERT_EQUAL( size_t(parallel ? 5 : 4) , tmp.size() ); 00316 STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) ); 00317 STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) ); 00318 if ( parallel ) 00319 STKUNIT_ASSERT( entity_0_1.bucket().member(part_shared) ); 00320 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) ); 00321 STKUNIT_ASSERT( entity_0_1.bucket().member(part_B_0) ); 00322 } 00323 else { 00324 STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() ); 00325 STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) ); 00326 STKUNIT_ASSERT( entity_0_1.bucket().member(part_shared) ); 00327 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) ); 00328 } 00329 00330 bulk.modification_end(); 00331 00332 // Now that modification_end has been called, entity_0_1 should 00333 // be in the new part (B_0) on all processes. 00334 00335 entity_0_1.bucket().supersets( tmp ); 00336 if ( entity_0_1.owner_rank() == p_rank ) { 00337 STKUNIT_ASSERT_EQUAL( size_t(parallel ? 5 : 4) , tmp.size() ); 00338 STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) ); 00339 STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) ); 00340 if ( parallel ) 00341 STKUNIT_ASSERT( entity_0_1.bucket().member(part_shared) ); 00342 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) ); 00343 STKUNIT_ASSERT( entity_0_1.bucket().member(part_B_0) ); 00344 } 00345 else { 00346 STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() ); 00347 STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) ); 00348 STKUNIT_ASSERT( entity_0_1.bucket().member(part_shared) ); 00349 STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) ); 00350 STKUNIT_ASSERT( entity_0_1.bucket().member(part_B_0) ); 00351 } 00352 } 00353 00354 //---------------------------------------------------------------------- 00355 //---------------------------------------------------------------------- 00356 00357 STKUNIT_UNIT_TEST(UnitTestingOfBulkData, testChangeParts_ringmesh) 00358 { 00359 // This unit test tests part operations and verifies operations 00360 // by looking at bucket supersets. We use RingMesh for a slightly 00361 // more realistic test than the test above but it's a bit harder 00362 // to read. 00363 00364 stk_classic::ParallelMachine pm = MPI_COMM_WORLD; 00365 MPI_Barrier( pm ); 00366 00367 const unsigned nPerProc = 10; 00368 const unsigned p_rank = stk_classic::parallel_machine_rank( pm ); 00369 const unsigned p_size = stk_classic::parallel_machine_size( pm ); 00370 const unsigned nLocalNode = nPerProc + ( 1 < p_size ? 1 : 0 ); 00371 const unsigned nLocalEdge = nPerProc ; 00372 00373 // Create the ring mesh 00374 00375 RingFixture ring_mesh( pm , nPerProc , true /* generate parts */ ); 00376 ring_mesh.m_meta_data.commit(); 00377 BulkData& bulk = ring_mesh.m_bulk_data; 00378 00379 bulk.modification_begin(); 00380 ring_mesh.generate_mesh( ); 00381 STKUNIT_ASSERT(stk_classic::unit_test::modification_end_wrapper(bulk, 00382 false /* no aura */)); 00383 00384 bulk.modification_begin(); 00385 ring_mesh.fixup_node_ownership(); 00386 STKUNIT_ASSERT(stk_classic::unit_test::modification_end_wrapper(bulk, 00387 false /* no aura */)); 00388 00389 Part & part_owns = ring_mesh.m_meta_data.locally_owned_part(); 00390 Part & part_univ = ring_mesh.m_meta_data.universal_part(); 00391 00392 // Check that local edges are in the expected parts. Note that the 00393 // RingMesh puts each edge in its own part. 00394 for ( unsigned i = 0 ; i < nLocalEdge ; ++i ) { 00395 const unsigned n = i + nPerProc * p_rank ; 00396 Entity * const edge = bulk.get_entity( 1 /*entity rank*/, 00397 ring_mesh.m_edge_ids[n] ); 00398 STKUNIT_ASSERT( edge != NULL ); 00399 STKUNIT_ASSERT( edge->bucket().member( part_univ ) ); 00400 STKUNIT_ASSERT( edge->bucket().member( part_owns ) ); 00401 STKUNIT_ASSERT( edge->bucket().member( * ring_mesh.m_edge_parts[ n % ring_mesh.m_edge_parts.size() ] ) ); 00402 } 00403 00404 // Check that local nodes are in the expected parts. Note that the relations 00405 // that nodes have to edges should cause induced membership of the node 00406 // in the parts of both edges it touches. 00407 for ( unsigned i = 0 ; i < nLocalNode ; ++i ) { 00408 const unsigned n = ( i + nPerProc * p_rank ) % ring_mesh.m_node_ids.size(); 00409 const unsigned e0 = n ; 00410 const unsigned e1 = ( n + ring_mesh.m_edge_ids.size() - 1 ) % ring_mesh.m_edge_ids.size(); 00411 const unsigned ns = ring_mesh.m_edge_parts.size(); 00412 const unsigned n0 = e0 % ns ; 00413 const unsigned n1 = e1 % ns ; 00414 Part * const epart_0 = ring_mesh.m_edge_parts[ n0 < n1 ? n0 : n1 ]; 00415 Part * const epart_1 = ring_mesh.m_edge_parts[ n0 < n1 ? n1 : n0 ]; 00416 00417 Entity * const node = bulk.get_entity( 0 , ring_mesh.m_node_ids[n] ); 00418 STKUNIT_ASSERT( node != NULL ); 00419 if ( node->owner_rank() == p_rank ) { 00420 STKUNIT_ASSERT( node->bucket().member( part_univ ) ); 00421 STKUNIT_ASSERT( node->bucket().member( part_owns ) ); 00422 STKUNIT_ASSERT( node->bucket().member( *epart_0 ) ); 00423 STKUNIT_ASSERT( node->bucket().member( *epart_1 ) ); 00424 } 00425 else { 00426 STKUNIT_ASSERT( node->bucket().member( part_univ ) ); 00427 STKUNIT_ASSERT( ! node->bucket().member( part_owns ) ); 00428 STKUNIT_ASSERT( node->bucket().member( * epart_0 ) ); 00429 STKUNIT_ASSERT( node->bucket().member( * epart_1 ) ); 00430 } 00431 } 00432 00433 bulk.modification_begin(); 00434 00435 // On rank 0, change all locally owned edges to the extra-part then check 00436 // for correct part membership 00437 if ( 0 == p_rank ) { 00438 for ( unsigned i = 0 ; i < nLocalEdge ; ++i ) { 00439 const unsigned n = i + nPerProc * p_rank ; 00440 00441 PartVector add(1); add[0] = & ring_mesh.m_edge_part_extra ; 00442 PartVector rem(1); rem[0] = ring_mesh.m_edge_parts[ n % ring_mesh.m_edge_parts.size() ]; 00443 00444 Entity * const edge = bulk.get_entity( 1 , ring_mesh.m_edge_ids[n] ); 00445 bulk.change_entity_parts( *edge , add , rem ); 00446 STKUNIT_ASSERT( edge->bucket().member( part_univ ) ); 00447 STKUNIT_ASSERT( edge->bucket().member( part_owns ) ); 00448 STKUNIT_ASSERT( edge->bucket().member(ring_mesh.m_edge_part_extra ) ); 00449 } 00450 } 00451 00452 bulk.modification_end(); 00453 00454 // Modification end has been called, check that the part changes made 00455 // in the previous step are reflected across the other procs. 00456 for ( unsigned i = 0 ; i < nLocalNode ; ++i ) { 00457 const unsigned n = ( i + nPerProc * p_rank ) % ring_mesh.m_node_ids.size(); 00458 const unsigned e0 = n ; 00459 const unsigned e1 = ( n + ring_mesh.m_edge_ids.size() - 1 ) % ring_mesh.m_edge_ids.size(); 00460 const unsigned ns = ring_mesh.m_edge_parts.size(); 00461 const unsigned n0 = e0 % ns ; 00462 const unsigned n1 = e1 % ns ; 00463 Part * ep_0 = e0 < nLocalEdge ? & ring_mesh.m_edge_part_extra : ring_mesh.m_edge_parts[n0] ; 00464 Part * ep_1 = e1 < nLocalEdge ? & ring_mesh.m_edge_part_extra : ring_mesh.m_edge_parts[n1] ; 00465 00466 Part * epart_0 = ep_0->mesh_meta_data_ordinal() < ep_1->mesh_meta_data_ordinal() ? ep_0 : ep_1 ; 00467 Part * epart_1 = ep_0->mesh_meta_data_ordinal() < ep_1->mesh_meta_data_ordinal() ? ep_1 : ep_0 ; 00468 00469 Entity * const node = bulk.get_entity( 0 , ring_mesh.m_node_ids[n] ); 00470 STKUNIT_ASSERT( node != NULL ); 00471 if ( node->owner_rank() == p_rank ) { 00472 STKUNIT_ASSERT( node->bucket().member( part_owns ) ); 00473 } 00474 else { 00475 STKUNIT_ASSERT( ! node->bucket().member( part_owns ) ); 00476 } 00477 00478 STKUNIT_ASSERT( node->bucket().member( part_univ ) ); 00479 STKUNIT_ASSERT( node->bucket().member( *epart_0 ) ); 00480 STKUNIT_ASSERT( node->bucket().member( *epart_1 ) ); 00481 } 00482 }