|
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 00010 #include <sstream> 00011 #include <stdexcept> 00012 00013 #include <stk_util/unit_test_support/stk_utest_macros.hpp> 00014 00015 #include <stk_util/parallel/Parallel.hpp> 00016 #include <stk_mesh/base/BulkData.hpp> 00017 #include <stk_mesh/base/GetEntities.hpp> 00018 #include <stk_mesh/base/EntityComm.hpp> 00019 #include <stk_mesh/base/Comm.hpp> 00020 #include <stk_mesh/fem/TopologicalMetaData.hpp> 00021 00022 #include <unit_tests/UnitTestBulkData.hpp> 00023 #include <unit_tests/UnitTestRingMeshFixture.hpp> 00024 00025 STKUNIT_UNIT_TEST(UnitTestingOfBulkData, testUnit) 00026 { 00027 MPI_Barrier( MPI_COMM_WORLD ); 00028 stk::mesh::UnitTestBulkData::testBulkData( MPI_COMM_WORLD ); 00029 stk::mesh::UnitTestBulkData::testChangeOwner_nodes( MPI_COMM_WORLD ); 00030 stk::mesh::UnitTestBulkData::testChangeOwner_loop( MPI_COMM_WORLD ); 00031 stk::mesh::UnitTestBulkData::testChangeOwner_box( MPI_COMM_WORLD ); 00032 stk::mesh::UnitTestBulkData::testCreateMore( MPI_COMM_WORLD ); 00033 stk::mesh::UnitTestBulkData::testChangeParts( MPI_COMM_WORLD ); 00034 stk::mesh::UnitTestBulkData::testChangeParts_loop( MPI_COMM_WORLD ); 00035 stk::mesh::UnitTestBulkData::testDestroy_nodes( MPI_COMM_WORLD ); 00036 stk::mesh::UnitTestBulkData::testDestroy_loop( MPI_COMM_WORLD ); 00037 stk::mesh::UnitTestBulkData::testModifyPropagation( MPI_COMM_WORLD ); 00038 } 00039 00040 //---------------------------------------------------------------------- 00041 //---------------------------------------------------------------------- 00042 00043 00044 00045 namespace stk { 00046 namespace mesh { 00047 00048 bool UnitTestBulkData::modification_end( BulkData & mesh , bool aura ) 00049 { return mesh.internal_modification_end( aura ); } 00050 00051 // Unit test the Part functionality in isolation: 00052 00053 void UnitTestBulkData::testBulkData( ParallelMachine pm ) 00054 { 00055 static const char method[] = "stk::mesh::UnitTestBulkData" ; 00056 00057 std::cout << std::endl ; 00058 00059 std::vector<std::string> entity_names(10); 00060 for ( size_t i = 0 ; i < 10 ; ++i ) { 00061 std::ostringstream name ; 00062 name << "EntityRank" << i ; 00063 entity_names[i] = name.str(); 00064 } 00065 00066 MetaData meta( entity_names ); 00067 00068 meta.commit(); 00069 00070 BulkData bulk( meta , pm , 100 ); 00071 00072 for ( size_t i = 0 ; i < 4 ; ++i ) { 00073 STKUNIT_ASSERT( bulk.modification_begin() ); 00074 STKUNIT_ASSERT_EQUAL( i , bulk.synchronized_count() ); 00075 STKUNIT_ASSERT( bulk.modification_end() ); 00076 } 00077 00078 std::vector<Part*> no_parts ; 00079 00080 Entity * e[10] ; 00081 00082 const unsigned id = bulk.parallel_rank() + 1 ; 00083 00084 STKUNIT_ASSERT( bulk.modification_begin() ); 00085 for ( size_t i = 0 ; i < 10 ; ++i ) { 00086 e[i] = & bulk.declare_entity( i , id , no_parts ); 00087 } 00088 STKUNIT_ASSERT( bulk.modification_end() ); 00089 00090 for ( size_t i = 0 ; i < 10 ; ++i ) { 00091 STKUNIT_ASSERT( e[i] == bulk.get_entity( i , id ) ); 00092 } 00093 00094 bool ok = false ; 00095 STKUNIT_ASSERT( bulk.modification_begin() ); 00096 try { 00097 bulk.declare_entity( 11 , id , no_parts ); 00098 } 00099 catch( const std::exception & x ) { 00100 std::cout << method << " correctly caught: " << x.what() << std::endl ; 00101 ok = true ; 00102 } 00103 STKUNIT_ASSERT( ok ); 00104 STKUNIT_ASSERT( bulk.modification_end() ); 00105 00106 // Catch not-ok-to-modify 00107 ok = false ; 00108 try { 00109 bulk.declare_entity( 0 , id + 1 , no_parts ); 00110 } 00111 catch( const std::exception & x ) { 00112 ok = true ; 00113 } 00114 STKUNIT_ASSERT( ok ); 00115 } 00116 00117 //---------------------------------------------------------------------- 00118 // Testing for mesh entities without relations 00119 00120 void UnitTestBulkData::testChangeOwner_nodes( ParallelMachine pm ) 00121 { 00122 enum { nPerProc = 10 }; 00123 const unsigned p_rank = parallel_machine_rank( pm ); 00124 const unsigned p_size = parallel_machine_size( pm ); 00125 const unsigned id_total = nPerProc * p_size ; 00126 const unsigned id_begin = nPerProc * p_rank ; 00127 const unsigned id_end = nPerProc * ( p_rank + 1 ); 00128 00129 const int spatial_dimension = 3; 00130 MetaData meta( TopologicalMetaData::entity_rank_names(spatial_dimension) ); 00131 BulkData bulk( meta , pm , 100 ); 00132 00133 const PartVector no_parts ; 00134 00135 meta.commit(); 00136 bulk.modification_begin(); 00137 00138 // Ids for all entities (all entities have type 0): 00139 00140 std::vector<EntityId> ids( id_total ); 00141 00142 for ( unsigned i = 0 ; i < id_total ; ++i ) { 00143 ids[i] = i + 1; 00144 } 00145 00146 // Declare just those entities in my range of ids: 00147 00148 for ( unsigned i = id_begin ; i < id_end ; ++i ) { 00149 bulk.declare_entity( 0 , ids[i] , no_parts ); 00150 } 00151 00152 STKUNIT_ASSERT( bulk.modification_end() ); 00153 00154 // Verify that I only have entities in my range: 00155 00156 for ( unsigned i = 0 ; i < id_total ; ++i ) { 00157 Entity * e = bulk.get_entity( 0 , ids[ i ] ); 00158 if ( id_begin <= i && i < id_end ) { 00159 STKUNIT_ASSERT( NULL != e ); 00160 } 00161 else { 00162 STKUNIT_ASSERT( NULL == e ); 00163 } 00164 } 00165 00166 // Test change owner no-op first: 00167 00168 std::vector<EntityProc> change ; 00169 00170 STKUNIT_ASSERT( bulk.modification_begin() ); 00171 bulk.change_entity_owner( change ); 00172 STKUNIT_ASSERT( bulk.modification_end() ); 00173 00174 for ( unsigned i = 0 ; i < id_total ; ++i ) { 00175 Entity * e = bulk.get_entity( 0 , ids[ i ] ); 00176 if ( id_begin <= i && i < id_end ) { 00177 STKUNIT_ASSERT( NULL != e ); 00178 } 00179 else { 00180 STKUNIT_ASSERT( NULL == e ); 00181 } 00182 } 00183 00184 // Can only test changing owner in parallel. 00185 00186 if ( 1 < p_size ) { 00187 // Give my last two ids to the next process 00188 // Get the previous process' last two ids 00189 00190 const unsigned p_give = ( p_rank + 1 ) % p_size ; 00191 const unsigned id_give = id_end - 2 ; 00192 const unsigned id_get = ( id_begin + id_total - 2 ) % id_total ; 00193 00194 STKUNIT_ASSERT( NULL != bulk.get_entity( 0 , ids[id_give] ) ); 00195 STKUNIT_ASSERT( NULL != bulk.get_entity( 0 , ids[id_give+1] ) ); 00196 STKUNIT_ASSERT( NULL == bulk.get_entity( 0 , ids[id_get] ) ); 00197 STKUNIT_ASSERT( NULL == bulk.get_entity( 0 , ids[id_get+1] ) ); 00198 00199 change.resize(2); 00200 change[0].first = bulk.get_entity( 0 , ids[id_give] ); 00201 change[0].second = p_give ; 00202 change[1].first = bulk.get_entity( 0 , ids[id_give+1] ); 00203 change[1].second = p_give ; 00204 00205 STKUNIT_ASSERT( bulk.modification_begin() ); 00206 bulk.change_entity_owner( change ); 00207 STKUNIT_ASSERT( bulk.modification_end() ); 00208 00209 STKUNIT_ASSERT( NULL != bulk.get_entity( 0 , ids[id_get] ) ); 00210 STKUNIT_ASSERT( NULL != bulk.get_entity( 0 , ids[id_get+1] ) ); 00211 00212 // Entities given away are destroyed until the next modification cycle 00213 { 00214 Entity * const e0 = bulk.get_entity( 0 , ids[id_give] ); 00215 Entity * const e1 = bulk.get_entity( 0 , ids[id_give+1] ); 00216 STKUNIT_ASSERT( NULL != e0 && e0->bucket().capacity() == 0 ); 00217 STKUNIT_ASSERT( NULL != e1 && e1->bucket().capacity() == 0 ); 00218 } 00219 00220 STKUNIT_ASSERT( bulk.modification_begin() ); 00221 STKUNIT_ASSERT( bulk.modification_end() ); 00222 00223 STKUNIT_ASSERT( NULL == bulk.get_entity( 0 , ids[id_give] ) ); 00224 STKUNIT_ASSERT( NULL == bulk.get_entity( 0 , ids[id_give+1] ) ); 00225 } 00226 00227 std::cout << std::endl 00228 << "P" << p_rank 00229 << ": UnitTestBulkData::testChangeOwner_nodes( NP = " 00230 << p_size << " ) SUCCESSFULL " << std::endl ; 00231 } 00232 00233 //---------------------------------------------------------------------- 00234 // Testing for creating existing mesh entities without relations 00235 00236 void UnitTestBulkData::testCreateMore( ParallelMachine pm ) 00237 { 00238 enum { nPerProc = 10 }; 00239 00240 const unsigned p_size = parallel_machine_size( pm ); 00241 const unsigned p_rank = parallel_machine_rank( pm ); 00242 00243 if ( 1 < p_size ) { 00244 00245 std::cout << std::endl 00246 << "P" << p_rank 00247 << ": UnitTestBulkData::testCreateMore( NP = " 00248 << p_size << " )" 00249 << std::endl ; 00250 std::cout.flush(); 00251 00252 const unsigned id_total = nPerProc * p_size ; 00253 const unsigned id_begin = nPerProc * p_rank ; 00254 const unsigned id_end = nPerProc * ( p_rank + 1 ); 00255 00256 const int spatial_dimension = 3; 00257 MetaData meta( TopologicalMetaData::entity_rank_names(spatial_dimension) ); 00258 00259 const PartVector no_parts ; 00260 00261 meta.commit(); 00262 00263 BulkData bulk( meta , pm , 100 ); 00264 00265 bulk.modification_begin(); 00266 00267 // Ids for all entities (all entities have type 0): 00268 00269 std::vector<EntityId> ids( id_total ); 00270 00271 for ( unsigned i = 0 ; i < id_total ; ++i ) { ids[i] = i + 1; } 00272 00273 // Declare just those entities in my range of ids: 00274 00275 for ( unsigned i = id_begin ; i < id_end ; ++i ) { 00276 bulk.declare_entity( 0 , ids[i] , no_parts ); 00277 } 00278 00279 STKUNIT_ASSERT( bulk.modification_end() ); 00280 00281 // Only one process create entities with previous process' last two ids 00282 00283 const unsigned id_get = ( id_begin + id_total - 2 ) % id_total ; 00284 00285 STKUNIT_ASSERT( NULL == bulk.get_entity( 0 , ids[id_get] ) ); 00286 STKUNIT_ASSERT( NULL == bulk.get_entity( 0 , ids[id_get+1] ) ); 00287 00288 STKUNIT_ASSERT( bulk.modification_begin() ); 00289 00290 if ( 1 == p_rank ) { 00291 // These declarations create entities that already exist, 00292 // which will be an error. Must create an owned entity 00293 // to use them, thus they become shared. 00294 00295 Entity & e0 = bulk.declare_entity( 0 , ids[ id_get ] , no_parts ); 00296 Entity & e1 = bulk.declare_entity( 0 , ids[ id_get + 1 ] , no_parts ); 00297 00298 Entity & eU = bulk.declare_entity( 1 , 1 , no_parts ); 00299 00300 bulk.declare_relation( eU , e0 , 0 ); 00301 bulk.declare_relation( eU , e1 , 1 ); 00302 } 00303 00304 bulk.modification_end(); 00305 00306 if ( 1 == p_rank ) { 00307 Entity * e0 = bulk.get_entity( 0 , ids[id_get] ); 00308 Entity * e1 = bulk.get_entity( 0 , ids[id_get+1] ); 00309 STKUNIT_ASSERT( NULL != e0 ); 00310 STKUNIT_ASSERT( NULL != e1 ); 00311 STKUNIT_ASSERT( 0 == e0->owner_rank() ); 00312 STKUNIT_ASSERT( 0 == e1->owner_rank() ); 00313 } 00314 00315 // Now test tripping the error condition 00316 00317 bulk.modification_begin(); 00318 00319 if ( 0 == p_rank ) { 00320 bulk.declare_entity( 0 , ids[ id_get ] , no_parts ); 00321 bulk.declare_entity( 0 , ids[ id_get + 1 ] , no_parts ); 00322 } 00323 00324 STKUNIT_ASSERT_THROW( bulk.modification_end() , std::runtime_error ); 00325 } 00326 } 00327 00328 //---------------------------------------------------------------------- 00329 //---------------------------------------------------------------------- 00330 00331 void UnitTestBulkData::testChangeOwner_loop( ParallelMachine pm ) 00332 { 00333 enum { nPerProc = 10 }; 00334 const unsigned p_rank = parallel_machine_rank( pm ); 00335 const unsigned p_size = parallel_machine_size( pm ); 00336 const unsigned nLocalNode = nPerProc + ( 1 < p_size ? 1 : 0 ); 00337 const unsigned nLocalEdge = nPerProc ; 00338 00339 std::vector<unsigned> local_count ; 00340 00341 //------------------------------ 00342 { 00343 UnitTestRingMeshFixture ring_mesh( pm , nPerProc , false /* no edge parts */ ); 00344 ring_mesh.m_meta_data.commit(); 00345 ring_mesh.generate_mesh( false /* no aura */ ); 00346 00347 const Selector select_used = ring_mesh.m_meta_data.locally_owned_part() | 00348 ring_mesh.m_meta_data.globally_shared_part() ; 00349 const Selector select_all = ring_mesh.m_meta_data.universal_part() ; 00350 00351 count_entities( select_used , ring_mesh.m_bulk_data , local_count ); 00352 STKUNIT_ASSERT_EQUAL( local_count[0] , nLocalNode ); 00353 STKUNIT_ASSERT_EQUAL( local_count[1] , nLocalEdge ); 00354 00355 count_entities( select_all , ring_mesh.m_bulk_data , local_count ); 00356 STKUNIT_ASSERT_EQUAL( local_count[0] , nLocalNode ); 00357 STKUNIT_ASSERT_EQUAL( local_count[1] , nLocalEdge ); 00358 00359 // Shift loop by two nodes and edges. 00360 00361 if ( 1 < p_size ) { 00362 ring_mesh.test_shift_loop( false /* no aura */ ); 00363 00364 count_entities( select_used , ring_mesh.m_bulk_data , local_count ); 00365 STKUNIT_ASSERT( local_count[0] == nLocalNode ); 00366 STKUNIT_ASSERT( local_count[1] == nLocalEdge ); 00367 00368 count_entities( select_all , ring_mesh.m_bulk_data , local_count ); 00369 STKUNIT_ASSERT( local_count[0] == nLocalNode ); 00370 STKUNIT_ASSERT( local_count[1] == nLocalEdge ); 00371 } 00372 } 00373 00374 //------------------------------ 00375 // Test shift starting with ghosting but not regenerated ghosting. 00376 { 00377 UnitTestRingMeshFixture ring_mesh( pm , nPerProc , false /* no edge parts */ ); 00378 ring_mesh.m_meta_data.commit(); 00379 ring_mesh.generate_mesh( true /* with aura */ ); 00380 00381 const Selector select_owned( ring_mesh.m_meta_data.locally_owned_part() ); 00382 const Selector select_used = ring_mesh.m_meta_data.locally_owned_part() | 00383 ring_mesh.m_meta_data.globally_shared_part() ; 00384 const Selector select_all( ring_mesh.m_meta_data.universal_part() ); 00385 00386 count_entities( select_used , ring_mesh.m_bulk_data , local_count ); 00387 STKUNIT_ASSERT_EQUAL( local_count[0] , nLocalNode ); 00388 STKUNIT_ASSERT_EQUAL( local_count[1] , nLocalEdge ); 00389 00390 count_entities( select_all , ring_mesh.m_bulk_data , local_count ); 00391 const unsigned n_extra = 1 < p_size ? 2 : 0 ; 00392 STKUNIT_ASSERT( local_count[0] == nLocalNode + n_extra ); 00393 STKUNIT_ASSERT( local_count[1] == nLocalEdge + n_extra ); 00394 00395 if ( 1 < p_size ) { 00396 ring_mesh.test_shift_loop( false /* no aura */ ); 00397 00398 count_entities( select_owned , ring_mesh.m_bulk_data , local_count ); 00399 STKUNIT_ASSERT( local_count[0] == nPerProc ); 00400 STKUNIT_ASSERT( local_count[1] == nPerProc ); 00401 00402 count_entities( select_used , ring_mesh.m_bulk_data , local_count ); 00403 STKUNIT_ASSERT( local_count[0] == nLocalNode ); 00404 STKUNIT_ASSERT( local_count[1] == nLocalEdge ); 00405 00406 // All of my ghosts were disrupted and therefore deleted: 00407 count_entities( select_all , ring_mesh.m_bulk_data , local_count ); 00408 STKUNIT_ASSERT_EQUAL( nLocalEdge , local_count[1] ); 00409 STKUNIT_ASSERT_EQUAL( nLocalNode , local_count[0] ); 00410 } 00411 } 00412 //------------------------------ 00413 // Test shift starting with ghosting and regenerating ghosting. 00414 { 00415 UnitTestRingMeshFixture ring_mesh( pm , nPerProc , false /* no edge parts */ ); 00416 ring_mesh.m_meta_data.commit(); 00417 ring_mesh.generate_mesh( true /* with aura */ ); 00418 00419 const Selector select_owned( ring_mesh.m_meta_data.locally_owned_part() ); 00420 const Selector select_used = ring_mesh.m_meta_data.locally_owned_part() | 00421 ring_mesh.m_meta_data.globally_shared_part() ; 00422 const Selector select_all( ring_mesh.m_meta_data.universal_part() ); 00423 00424 count_entities( select_used , ring_mesh.m_bulk_data , local_count ); 00425 STKUNIT_ASSERT( local_count[0] == nLocalNode ); 00426 STKUNIT_ASSERT( local_count[1] == nLocalEdge ); 00427 00428 count_entities( select_all , ring_mesh.m_bulk_data , local_count ); 00429 const unsigned n_extra = 1 < p_size ? 2 : 0 ; 00430 STKUNIT_ASSERT( local_count[0] == nLocalNode + n_extra ); 00431 STKUNIT_ASSERT( local_count[1] == nLocalEdge + n_extra ); 00432 00433 if ( 1 < p_size ) { 00434 ring_mesh.test_shift_loop( true /* with aura */ ); 00435 00436 count_entities( select_owned , ring_mesh.m_bulk_data , local_count ); 00437 STKUNIT_ASSERT( local_count[0] == nPerProc ); 00438 STKUNIT_ASSERT( local_count[1] == nPerProc ); 00439 00440 count_entities( select_used , ring_mesh.m_bulk_data , local_count ); 00441 STKUNIT_ASSERT( local_count[0] == nLocalNode ); 00442 STKUNIT_ASSERT( local_count[1] == nLocalEdge ); 00443 00444 // All of my ghosts were regenerated: 00445 count_entities( select_all , ring_mesh.m_bulk_data , local_count ); 00446 STKUNIT_ASSERT( local_count[0] == nLocalNode + n_extra ); 00447 STKUNIT_ASSERT( local_count[1] == nLocalEdge + n_extra ); 00448 } 00449 } 00450 //------------------------------ 00451 // Test bad owner change catching: 00452 if ( 1 < p_size ) { 00453 UnitTestRingMeshFixture ring_mesh( pm , nPerProc , false /* no edge parts */ ); 00454 ring_mesh.m_meta_data.commit(); 00455 ring_mesh.generate_mesh( true /* with aura */ ); 00456 00457 std::vector<EntityProc> change ; 00458 00459 if ( 0 == p_rank ) { 00460 change.resize(4); 00461 // Error to change to bad owner: 00462 change[0].first = ring_mesh.m_bulk_data.get_entity( 0 , ring_mesh.m_node_ids[1] ); 00463 change[0].second = p_size ; 00464 // Error to change a ghost: 00465 for ( std::vector<Entity*>::const_iterator 00466 ec = ring_mesh.m_bulk_data.entity_comm().begin() ; 00467 ec != ring_mesh.m_bulk_data.entity_comm().end() ; ++ec ) { 00468 if ( in_receive_ghost( **ec ) ) { 00469 change[1].first = *ec ; 00470 break ; 00471 } 00472 } 00473 change[1].second = p_rank ; 00474 // Error to change to multiple owners: 00475 change[2].first = ring_mesh.m_bulk_data.get_entity( 0 , ring_mesh.m_node_ids[1] ); 00476 change[2].second = ( p_rank + 1 ) % p_size ; 00477 change[3].first = change[2].first ; 00478 change[3].second = ( p_rank + 2 ) % p_size ; 00479 } 00480 00481 STKUNIT_ASSERT( ring_mesh.m_bulk_data.modification_begin() ); 00482 00483 std::string error_msg ; 00484 bool exception_thrown = false ; 00485 try { 00486 ring_mesh.m_bulk_data.change_entity_owner( change ); 00487 } 00488 catch( const std::exception & x ) { 00489 exception_thrown = true ; 00490 error_msg.assign( x.what() ); 00491 } 00492 STKUNIT_ASSERT( exception_thrown ); 00493 std::cout 00494 << std::endl 00495 << " UnitTestBulkData::testChangeOwner_loop SUCCESSFULLY CAUGHT: " 00496 << error_msg << std::endl ; 00497 std::cout.flush(); 00498 } 00499 //------------------------------ 00500 // Test move one element with initial ghosting but not regenerated ghosting: 00501 // last processor give its shared node to P0 00502 if ( 1 < p_size ) { 00503 UnitTestRingMeshFixture ring_mesh( pm , nPerProc , false /* no edge parts */ ); 00504 ring_mesh.m_meta_data.commit(); 00505 ring_mesh.generate_mesh( true /* with aura */ ); 00506 00507 const Selector select_owned( ring_mesh.m_meta_data.locally_owned_part() ); 00508 const Selector select_used = ring_mesh.m_meta_data.locally_owned_part() | 00509 ring_mesh.m_meta_data.globally_shared_part() ; 00510 const Selector select_all( ring_mesh.m_meta_data.universal_part() ); 00511 00512 std::vector<EntityProc> change ; 00513 00514 if ( p_rank + 1 == p_size ) { 00515 EntityProc entry ; 00516 entry.first = ring_mesh.m_bulk_data.get_entity( 0 , ring_mesh.m_node_ids[0] ); 00517 entry.second = 0 ; 00518 STKUNIT_ASSERT_EQUAL( p_rank , entry.first->owner_rank() ); 00519 change.push_back( entry ); 00520 } 00521 00522 STKUNIT_ASSERT( ring_mesh.m_bulk_data.modification_begin() ); 00523 ring_mesh.m_bulk_data.change_entity_owner( change ); 00524 STKUNIT_ASSERT( UnitTestBulkData::modification_end( ring_mesh.m_bulk_data , false ) ); 00525 00526 count_entities( select_owned , ring_mesh.m_bulk_data , local_count ); 00527 const unsigned n_node = p_rank == 0 ? nPerProc + 1 : ( 00528 p_rank + 1 == p_size ? nPerProc - 1 : 00529 nPerProc ); 00530 00531 STKUNIT_ASSERT_EQUAL( n_node , local_count[0] ); 00532 STKUNIT_ASSERT_EQUAL( (unsigned) nPerProc , local_count[1] ); 00533 00534 count_entities( select_used , ring_mesh.m_bulk_data , local_count ); 00535 STKUNIT_ASSERT_EQUAL( nLocalNode , local_count[0] ); 00536 STKUNIT_ASSERT_EQUAL( nLocalEdge , local_count[1] ); 00537 00538 // Moving the node disrupted ghosting on first and last process 00539 count_entities( select_all , ring_mesh.m_bulk_data , local_count ); 00540 const unsigned n_extra = p_rank + 1 == p_size || p_rank == 0 ? 1 : 2 ; 00541 STKUNIT_ASSERT_EQUAL( nLocalNode + n_extra , local_count[0] ); 00542 STKUNIT_ASSERT_EQUAL( nLocalEdge + n_extra , local_count[1] ); 00543 } 00544 00545 //------------------------------ 00546 00547 std::cout << std::endl 00548 << "P" << p_rank 00549 << ": UnitTestBulkData::testChangeOwner_loop( NP = " 00550 << p_size << " ) SUCCESSFULL" << std::endl ; 00551 } 00552 00553 //---------------------------------------------------------------------- 00554 //---------------------------------------------------------------------- 00555 // Testing for collection of boxes 00556 00557 namespace { 00558 00559 void donate_one_element( BulkData & mesh , bool aura ) 00560 { 00561 const unsigned p_rank = mesh.parallel_rank(); 00562 00563 Selector select_owned( mesh.mesh_meta_data().locally_owned_part() ); 00564 00565 std::vector<unsigned> before_count ; 00566 std::vector<unsigned> after_count ; 00567 00568 count_entities( select_owned , mesh , before_count ); 00569 00570 // Change owner of an element on a process boundary 00571 // from P0 to P1, and then recount to confirm ownership change 00572 00573 std::vector<EntityProc> change ; 00574 00575 // A shared node: 00576 Entity * node = NULL ; 00577 Entity * elem = NULL ; 00578 00579 for ( std::vector<Entity*>::const_iterator 00580 i = mesh.entity_comm().begin() ; 00581 i != mesh.entity_comm().end() ; ++i ) { 00582 if ( in_shared( **i ) && (**i).entity_rank() == BaseEntityRank ) { 00583 node = *i ; 00584 break ; 00585 } 00586 } 00587 00588 STKUNIT_ASSERT( node != NULL ); 00589 00590 for ( PairIterRelation rel = node->relations( 3 ); 00591 ! rel.empty() && elem == NULL ; ++rel ) { 00592 elem = rel->entity(); 00593 if ( elem->owner_rank() != p_rank ) { elem = NULL ; } 00594 } 00595 00596 STKUNIT_ASSERT( elem != NULL ); 00597 00598 unsigned donated_nodes = 0 ; 00599 00600 // Only process #0 donates an element and its owned nodes: 00601 if ( 0 == p_rank ) { 00602 EntityProc entry ; 00603 entry.first = elem ; 00604 entry.second = node->sharing()[0].proc ; 00605 change.push_back( entry ); 00606 for ( PairIterRelation 00607 rel = elem->relations(0) ; ! rel.empty() ; ++rel ) { 00608 if ( rel->entity()->owner_rank() == p_rank ) { 00609 entry.first = rel->entity(); 00610 change.push_back( entry ); 00611 ++donated_nodes ; 00612 } 00613 } 00614 } 00615 00616 STKUNIT_ASSERT( mesh.modification_begin() ); 00617 mesh.change_entity_owner( change ); 00618 STKUNIT_ASSERT( UnitTestBulkData::modification_end( mesh , aura ) ); 00619 00620 count_entities( select_owned , mesh , after_count ); 00621 00622 if ( 0 == p_rank ) { 00623 STKUNIT_ASSERT_EQUAL( before_count[3] - 1 , after_count[3] ); 00624 STKUNIT_ASSERT_EQUAL( before_count[0] - donated_nodes, after_count[0] ); 00625 } 00626 } 00627 00628 void donate_all_shared_nodes( BulkData & mesh , bool aura ) 00629 { 00630 const unsigned p_rank = mesh.parallel_rank(); 00631 00632 const Selector select_used = mesh.mesh_meta_data().locally_owned_part() | 00633 mesh.mesh_meta_data().globally_shared_part() ; 00634 00635 std::vector<unsigned> before_count ; 00636 std::vector<unsigned> after_count ; 00637 00638 count_entities( select_used , mesh , before_count ); 00639 00640 // Donate owned shared nodes to first sharing process. 00641 00642 const std::vector<Entity*> & entity_comm = mesh.entity_comm(); 00643 00644 STKUNIT_ASSERT( ! entity_comm.empty() ); 00645 00646 std::vector<EntityProc> change ; 00647 00648 for ( std::vector<Entity*>::const_iterator 00649 i = entity_comm.begin() ; 00650 i != entity_comm.end() && 00651 (**i).entity_rank() == BaseEntityRank ; ++i ) { 00652 Entity * const node = *i ; 00653 const PairIterEntityComm ec = node->sharing(); 00654 00655 if ( node->owner_rank() == p_rank && ! ec.empty() ) { 00656 change.push_back( EntityProc( node , ec->proc ) ); 00657 } 00658 } 00659 00660 STKUNIT_ASSERT( mesh.modification_begin() ); 00661 mesh.change_entity_owner( change ); 00662 STKUNIT_ASSERT( UnitTestBulkData::modification_end( mesh , aura ) ); 00663 00664 count_entities( select_used , mesh , after_count ); 00665 00666 STKUNIT_ASSERT( 3 <= after_count.size() ); 00667 STKUNIT_ASSERT_EQUAL( before_count[0] , after_count[0] ); 00668 STKUNIT_ASSERT_EQUAL( before_count[1] , after_count[1] ); 00669 STKUNIT_ASSERT_EQUAL( before_count[2] , after_count[2] ); 00670 STKUNIT_ASSERT_EQUAL( before_count[3] , after_count[3] ); 00671 } 00672 00673 } 00674 00675 void UnitTestBulkData::testChangeOwner_box( ParallelMachine pm ) 00676 { 00677 const int root_box[3][2] = { { 0 , 4 } , { 0 , 5 } , { 0 , 6 } }; 00678 int local_box[3][2] = { { 0 , 0 } , { 0 , 0 } , { 0 , 0 } }; 00679 00680 const unsigned p_rank = parallel_machine_rank( pm ); 00681 const unsigned p_size = parallel_machine_size( pm ); 00682 00683 const int spatial_dimension = 3; 00684 MetaData meta( TopologicalMetaData::entity_rank_names(spatial_dimension) ); 00685 00686 meta.commit(); 00687 00688 const Selector select_owned( meta.locally_owned_part() ); 00689 const Selector select_used = meta.locally_owned_part() | 00690 meta.globally_shared_part() ; 00691 const Selector select_all( meta.universal_part() ); 00692 00693 //------------------------------ 00694 { 00695 BulkData bulk( meta , pm , 100 ); 00696 bulk.modification_begin(); 00697 generate_boxes( bulk , false /* no aura */ , root_box , local_box ); 00698 00699 if ( 1 < p_size ) { 00700 donate_one_element( bulk , false /* no aura */ ); 00701 } 00702 } 00703 00704 if ( 1 < p_size ) { 00705 BulkData bulk( meta , pm , 100 ); 00706 bulk.modification_begin(); 00707 00708 generate_boxes( bulk , false /* no aura */ , root_box , local_box ); 00709 00710 donate_all_shared_nodes( bulk , false /* no aura */ ); 00711 } 00712 //------------------------------ 00713 if ( 1 < p_size ) { 00714 BulkData bulk( meta , pm , 100 ); 00715 bulk.modification_begin(); 00716 00717 generate_boxes( bulk , false /* no aura */ , root_box , local_box ); 00718 00719 donate_one_element( bulk , false /* no aura */ ); 00720 } 00721 //------------------------------ 00722 // Introduce ghosts: 00723 if ( 1 < p_size ) { 00724 BulkData bulk( meta , pm , 100 ); 00725 bulk.modification_begin(); 00726 00727 generate_boxes( bulk , true /* aura */ , root_box , local_box ); 00728 00729 std::vector<unsigned> used_count ; 00730 std::vector<unsigned> all_count ; 00731 00732 count_entities( select_all , bulk , all_count ); 00733 count_entities( select_used , bulk , used_count ); 00734 00735 STKUNIT_ASSERT( used_count[0] < all_count[0] ); 00736 STKUNIT_ASSERT( used_count[3] < all_count[3] ); 00737 00738 donate_all_shared_nodes( bulk , false /* don't regenerate aura */ ); 00739 00740 count_entities( select_all , bulk , all_count ); 00741 count_entities( select_used , bulk , used_count ); 00742 00743 STKUNIT_ASSERT_EQUAL( used_count[0] , all_count[0] ); 00744 STKUNIT_ASSERT_EQUAL( used_count[3] , all_count[3] ); 00745 } 00746 //------------------------------ 00747 00748 std::cout << std::endl 00749 << "P" << p_rank 00750 << ": UnitTestBulkData::testChangeOwner_box( NP = " 00751 << p_size << " ) SUCCESSFULL" << std::endl ; 00752 } 00753 00754 void UnitTestBulkData::testModifyPropagation( ParallelMachine pm ) 00755 { 00756 const unsigned nPerProc = 2; 00757 const unsigned p_size = parallel_machine_size( pm ); 00758 00759 // this test only needs to be run w/ one processor 00760 if (p_size > 1) return; 00761 00762 // Make a ring_mesh and add an extra part 00763 UnitTestRingMeshFixture ring_mesh( pm , nPerProc, false /* don't use edge parts */); 00764 TopologicalMetaData & top_data = ring_mesh.m_top_data; 00765 stk::mesh::Part& special_part = 00766 ring_mesh.m_meta_data.declare_part( "special_node_part", stk::mesh::BaseEntityRank ); 00767 ring_mesh.m_meta_data.commit(); 00768 ring_mesh.generate_mesh(); 00769 00770 // grab the first edge 00771 stk::mesh::EntityVector edges; 00772 stk::mesh::get_entities( ring_mesh.m_bulk_data, top_data.edge_rank, edges ); 00773 stk::mesh::Entity& edge = *( edges.front() ); 00774 00775 // get one of the nodes related to this edge 00776 PairIterRelation node_relations = edge.relations( stk::mesh::BaseEntityRank ); 00777 STKUNIT_ASSERT( !node_relations.empty() ); 00778 stk::mesh::Entity& node = *( node_relations.front().entity()); 00779 STKUNIT_ASSERT_EQUAL( node.entity_rank(), (unsigned) stk::mesh::BaseEntityRank ); 00780 00781 // make a modification to the node by changing its parts 00782 ring_mesh.m_bulk_data.modification_begin(); 00783 stk::mesh::PartVector parts; 00784 parts.push_back( &special_part ); 00785 ring_mesh.m_bulk_data.change_entity_parts( node, parts ); 00786 00787 // check that the node AND it's edge are marked as modified 00788 STKUNIT_ASSERT_EQUAL ( node.log_query(), stk::mesh::EntityLogModified ); 00789 STKUNIT_ASSERT_EQUAL ( edge.log_query(), stk::mesh::EntityLogModified ); 00790 00791 STKUNIT_ASSERT ( ring_mesh.m_bulk_data.modification_end() ); 00792 } 00793 00794 //---------------------------------------------------------------------- 00795 //---------------------------------------------------------------------- 00796 00797 } // namespace mesh 00798 } // namespace stk 00799