|
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 <stdexcept> 00011 00012 #include <stk_util/unit_test_support/stk_utest_macros.hpp> 00013 #include <unit_tests/UnitTestMesh.hpp> 00014 00015 #include <stk_mesh/fixtures/HexFixture.hpp> 00016 #include <stk_mesh/fem/TopologyHelpers.hpp> 00017 #include <stk_mesh/fem/TopologicalMetaData.hpp> 00018 00019 #include <stk_mesh/base/EntityComm.hpp> 00020 00021 // UnitTestBulkData_new is the beginnings of a refactoring of the bulk 00022 // data unit test. It relies on the UnitTestMesh fixture to rapidly 00023 // create a mesh for testing. 00024 00025 00026 void new_insert_transitive_closure( std::set<stk::mesh::EntityProc,stk::mesh::EntityLess> & , 00027 const stk::mesh::EntityProc & entry ); 00028 void new_comm_sync_send_recv( 00029 stk::mesh::BulkData & mesh , 00030 std::set< stk::mesh::EntityProc , stk::mesh::EntityLess > & new_send , 00031 std::set< stk::mesh::Entity * , stk::mesh::EntityLess > & new_recv ); 00032 00033 void new_comm_recv_to_send( 00034 stk::mesh::BulkData & mesh , 00035 const std::set< stk::mesh::Entity * , stk::mesh::EntityLess > & new_recv , 00036 std::set< stk::mesh::EntityProc , stk::mesh::EntityLess > & new_send ); 00037 00038 00039 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyAssertOwnerDeletedEntity ) 00040 { 00041 stk::unit_test::UnitTestMesh fixture( MPI_COMM_WORLD ); 00042 00043 stk::mesh::BulkData &bulk = fixture.nonconst_bulk_data(); 00044 stk::mesh::Part &new_part = fixture.get_test_part (); 00045 stk::mesh::PartVector add_part; 00046 add_part.push_back ( &new_part ); 00047 00048 fixture.generate_boxes (); 00049 // Find a cell owned by this process 00050 stk::mesh::Entity *cell_to_delete = NULL; 00051 stk::mesh::Entity *cell_to_delete_copy = NULL; 00052 std::vector<stk::mesh::Bucket *>::const_iterator cur_bucket = bulk.buckets(3).begin(); 00053 while ( cur_bucket != bulk.buckets(3).end() ) 00054 { 00055 stk::mesh::Bucket::iterator cur_entity = (*cur_bucket)->begin(); 00056 while ( cur_entity != (*cur_bucket)->end() ) 00057 { 00058 if ( cur_entity->owner_rank() == fixture.comm_rank() ) 00059 { 00060 cell_to_delete = &*cur_entity; 00061 break; 00062 } 00063 cur_entity++; 00064 } 00065 cur_bucket++; 00066 } 00067 00068 STKUNIT_ASSERT ( cell_to_delete != NULL ); 00069 cell_to_delete_copy = cell_to_delete; 00070 bulk.modification_begin(); 00071 bulk.destroy_entity ( cell_to_delete ); 00072 // Destroying an already destroyed entity returns false 00073 STKUNIT_ASSERT( false == bulk.destroy_entity( cell_to_delete_copy ) ); 00074 bulk.modification_end(); 00075 } 00076 00077 00078 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyAssertGoodKey ) 00079 { 00080 stk::unit_test::UnitTestMesh fixture( MPI_COMM_WORLD ); 00081 00082 stk::mesh::BulkData &bulk = fixture.nonconst_bulk_data(); 00083 stk::mesh::Part &new_part = fixture.get_test_part (); 00084 stk::mesh::PartVector add_part; 00085 add_part.push_back ( &new_part ); 00086 00087 stk::mesh::EntityKey bad_key1 ( 45 , 1 ); // Bad entity rank 00088 stk::mesh::EntityKey bad_key2 ( 1 , 0 ); // Bad id 00089 00090 STKUNIT_ASSERT_THROW ( bulk.assert_good_key ( "method" , bad_key1 ) , std::runtime_error ); 00091 STKUNIT_ASSERT_THROW ( bulk.assert_good_key ( "method" , bad_key2 ) , std::runtime_error ); 00092 } 00093 00094 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyGetEntityGuards ) 00095 { 00096 stk::unit_test::UnitTestMesh fixture( MPI_COMM_WORLD ); 00097 00098 stk::mesh::BulkData &bulk = fixture.nonconst_bulk_data(); 00099 STKUNIT_ASSERT_THROW ( bulk.get_entity ( 1 , 0 ) , std::runtime_error ); 00100 } 00101 00102 00103 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyExplicitAddInducedPart ) 00104 { 00105 stk::unit_test::UnitTestMesh fixture( MPI_COMM_WORLD ); 00106 stk::mesh::BulkData &bulk = fixture.nonconst_bulk_data (); 00107 stk::mesh::PartVector empty_vector; 00108 stk::mesh::PartVector cell_part_vector; 00109 00110 bulk.modification_begin(); 00111 00112 stk::mesh::Entity &new_cell = bulk.declare_entity ( 3 , fixture.comm_rank()+1 , empty_vector ); 00113 stk::mesh::Entity &new_node = bulk.declare_entity ( 0 , fixture.comm_rank()+1 , empty_vector ); 00114 00115 bulk.declare_relation ( new_cell , new_node , 1 ); 00116 00117 cell_part_vector.push_back ( &fixture.get_cell_part () ); 00118 bulk.change_entity_parts ( new_cell , cell_part_vector ); 00119 STKUNIT_ASSERT_THROW ( bulk.change_entity_parts ( new_node , cell_part_vector ) , std::runtime_error ); 00120 } 00121 00122 /************************ 00123 * This unit test is not possible currently because of the lack of 00124 * separation between internal part modification routines and public 00125 * part modification routines. 00126 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyCannotRemoveFromSpecialParts ) 00127 { 00128 stk::unit_test::UnitTestMesh fixture; 00129 stk::mesh::BulkData &bulk = fixture.nonconst_bulk_data(); 00130 stk::mesh::PartVector test_parts; 00131 stk::mesh::PartVector out_parts; 00132 stk::mesh::PartVector empty_vector; 00133 00134 stk::mesh::Entity &new_cell = bulk.declare_entity ( 3 , fixture.comm_rank()+1 , empty_vector ); 00135 test_parts.push_back ( &fixture.meta_data().universal_part() ); 00136 STKUNIT_ASSERT_THROW ( bulk.change_entity_parts ( new_cell , empty_vector , test_parts ) , std::runtime_error ); 00137 test_parts.clear(); 00138 test_parts.push_back ( &fixture.meta_data().locally_owned_part() ); 00139 STKUNIT_ASSERT_THROW ( bulk.change_entity_parts ( new_cell , empty_vector , test_parts ) , std::runtime_error ); 00140 test_parts.clear(); 00141 test_parts.push_back ( &fixture.meta_data().globally_shared_part() ); 00142 STKUNIT_ASSERT_THROW ( bulk.change_entity_parts ( new_cell , empty_vector , test_parts ) , std::runtime_error ); 00143 } 00144 */ 00145 00146 00147 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyDefaultPartAddition ) 00148 { 00149 stk::unit_test::UnitTestMesh fixture( MPI_COMM_WORLD ); 00150 stk::mesh::BulkData &bulk = fixture.nonconst_bulk_data (); 00151 00152 bulk.modification_begin(); 00153 stk::mesh::Entity &new_cell = fixture.get_new_entity ( 3 , 1 ); 00154 bulk.modification_end(); 00155 00156 STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.meta_data().universal_part() ) ); 00157 STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.meta_data().locally_owned_part() ) ); 00158 } 00159 00160 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyChangePartsSerial ) 00161 { 00162 stk::unit_test::UnitTestMesh fixture( MPI_COMM_WORLD ); 00163 stk::mesh::BulkData &bulk = fixture.nonconst_bulk_data (); 00164 stk::mesh::PartVector create_parts , remove_parts , add_parts, empty_parts; 00165 00166 create_parts.push_back ( &fixture.get_test_part() ); 00167 create_parts.push_back ( &fixture.get_part_a_3() ); 00168 remove_parts.push_back ( &fixture.get_part_a_3() ); 00169 add_parts.push_back ( &fixture.get_part_b_superset() ); 00170 add_parts.push_back ( &fixture.get_cell_part() ); 00171 00172 bulk.modification_begin(); 00173 stk::mesh::Entity &new_cell = fixture.get_new_entity ( 3 , 1 ); 00174 bulk.change_entity_parts ( new_cell , create_parts , empty_parts ); 00175 bulk.modification_end(); 00176 STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_test_part() ) ); 00177 STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_part_a_3() ) ); 00178 STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_part_a_superset() ) ); 00179 STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_part_b_superset() ) ); 00180 STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_cell_part() ) ); 00181 00182 bulk.modification_begin(); 00183 bulk.change_entity_parts ( new_cell , add_parts , remove_parts ); 00184 bulk.modification_end(); 00185 STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_test_part() ) ); 00186 STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_part_a_3() ) ); 00187 STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_part_a_superset() ) ); 00188 STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_part_b_superset() ) ); 00189 STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_cell_part() ) ); 00190 00191 bulk.modification_begin(); 00192 bulk.change_entity_parts ( new_cell , empty_parts , add_parts ); 00193 bulk.modification_end(); 00194 STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_test_part() ) ); 00195 STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_part_a_3() ) ); 00196 STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_part_a_superset() ) ); 00197 STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_part_b_superset() ) ); 00198 STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_cell_part() ) ); 00199 00200 //Verify still a member of default parts 00201 STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.meta_data().universal_part() ) ); 00202 STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.meta_data().locally_owned_part() ) ); 00203 } 00204 00205 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyParallelAddParts ) 00206 { 00207 stk::unit_test::UnitTestMesh fixture( MPI_COMM_WORLD ); 00208 stk::mesh::BulkData &bulk = fixture.nonconst_bulk_data (); 00209 stk::mesh::PartVector add_part; 00210 00211 add_part.push_back ( &fixture.get_part_a_0() ); 00212 fixture.generate_boxes (); 00213 00214 bulk.modification_begin(); 00215 00216 for ( std::vector<stk::mesh::Entity*>::const_iterator 00217 cur_entity = bulk.entity_comm().begin(); 00218 cur_entity != bulk.entity_comm().end() ; ++cur_entity ) { 00219 stk::mesh::Entity & entity = **cur_entity ; 00220 if ( entity.entity_rank() == 0 ) { 00221 if ( entity.owner_rank() == fixture.comm_rank() ) { 00222 bulk.change_entity_parts ( entity, add_part, stk::mesh::PartVector() ); 00223 } 00224 } 00225 } 00226 00227 bulk.modification_end(); 00228 00229 for ( std::vector<stk::mesh::Entity*>::const_iterator 00230 cur_entity = bulk.entity_comm().begin(); 00231 cur_entity != bulk.entity_comm().end() ; ++cur_entity ) { 00232 stk::mesh::Entity & entity = **cur_entity ; 00233 if ( entity.entity_rank() == 0 ) { 00234 STKUNIT_ASSERT ( entity.bucket().member ( fixture.get_part_a_0 () ) ); 00235 } 00236 } 00237 } 00238 00239 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyInducedMembership ) 00240 { 00241 stk::unit_test::UnitTestMesh fixture( MPI_COMM_WORLD ); 00242 stk::mesh::BulkData &bulk = fixture.nonconst_bulk_data (); 00243 stk::mesh::PartVector create_node_parts , create_cell_parts , empty_parts; 00244 00245 create_node_parts.push_back ( &fixture.get_part_a_0() ); 00246 create_cell_parts.push_back ( &fixture.get_cell_part() ); 00247 00248 bulk.modification_begin(); 00249 00250 stk::mesh::Entity &node = fixture.get_new_entity ( 0 , 1 ); 00251 stk::mesh::Entity &cell = fixture.get_new_entity ( 3 , 1 ); 00252 00253 bulk.modification_begin(); 00254 00255 bulk.change_entity_parts ( node , create_node_parts , stk::mesh::PartVector () ); 00256 bulk.change_entity_parts ( cell , create_cell_parts , stk::mesh::PartVector () ); 00257 // Add node to cell part 00258 bulk.declare_relation ( cell , node , 0 ); 00259 bulk.modification_end(); 00260 00261 STKUNIT_ASSERT ( node.bucket().member ( fixture.get_cell_part() ) ); 00262 00263 bulk.modification_begin(); 00264 bulk.destroy_relation ( cell , node ); 00265 bulk.modification_end(); 00266 00267 STKUNIT_ASSERT ( !node.bucket().member ( fixture.get_cell_part() ) ); 00268 } 00269 00270 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyCanRemoveFromSetWithDifferentRankSubset ) 00271 { 00272 stk::unit_test::UnitTestMesh fixture( MPI_COMM_WORLD ); 00273 stk::mesh::BulkData &bulk = fixture.nonconst_bulk_data (); 00274 stk::mesh::PartVector add_parts , remove_parts, empty_parts; 00275 00276 add_parts.push_back ( &fixture.get_part_b_3() ); 00277 add_parts.push_back ( &fixture.get_part_a_superset() ); 00278 00279 remove_parts.push_back ( &fixture.get_part_a_superset() ); 00280 00281 bulk.modification_begin(); 00282 00283 stk::mesh::Entity &e = bulk.declare_entity ( 3 , fixture.comm_rank()+1 , add_parts ); 00284 bulk.modification_end(); 00285 00286 bulk.modification_begin(); 00287 bulk.change_entity_parts ( e , empty_parts , remove_parts ); 00288 bulk.modification_end(); 00289 00290 STKUNIT_ASSERT ( e.bucket().member ( fixture.get_part_b_3() ) ); 00291 STKUNIT_ASSERT ( !e.bucket().member ( fixture.get_part_a_superset() ) ); 00292 } 00293 00294 00295 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyCommonGhostingName ) 00296 { 00297 00298 stk::unit_test::UnitTestMesh fixture( MPI_COMM_WORLD ); 00299 stk::mesh::BulkData &bulk = fixture.nonconst_bulk_data (); 00300 00301 bulk.modification_begin(); 00302 00303 if ( fixture.comm_size() == 1 ) return; 00304 00305 if ( fixture.comm_rank() == 0 ) 00306 { 00307 STKUNIT_ASSERT_THROW ( bulk.create_ghosting ( "Name 1" ) , std::runtime_error ); 00308 } 00309 else 00310 { 00311 STKUNIT_ASSERT_THROW ( bulk.create_ghosting ( "Name 2" ) , std::runtime_error ); 00312 } 00313 } 00314 00315 00316 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyTrivialDestroyAllGhostings ) 00317 { 00318 stk::unit_test::UnitTestMesh fixture( MPI_COMM_WORLD ); 00319 00320 if ( fixture.comm_size() == 1 ) return; 00321 00322 fixture.generate_boxes (); 00323 00324 stk::mesh::BulkData &bulk = fixture.nonconst_bulk_data(); 00325 00326 bulk.modification_begin(); 00327 00328 stk::mesh::Ghosting &ghosting = bulk.create_ghosting ( "Ghost 1" ); 00329 00330 // Find a cell owned by this process 00331 std::vector<stk::mesh::Bucket *>::const_iterator cur_bucket = bulk.buckets(3).begin(); 00332 unsigned send_rank = 0; 00333 00334 std::vector<stk::mesh::EntityProc> to_send; 00335 std::vector<stk::mesh::Entity *> empty_vector; 00336 while ( cur_bucket != bulk.buckets(3).end() ) 00337 { 00338 stk::mesh::Bucket::iterator cur_entity = (*cur_bucket)->begin(); 00339 while ( cur_entity != (*cur_bucket)->end() ) 00340 { 00341 if ( cur_entity->owner_rank() == fixture.comm_rank() ) 00342 { 00343 if ( send_rank == fixture.comm_size() ) send_rank = 0; 00344 if ( send_rank != fixture.comm_rank() ) 00345 to_send.push_back ( std::make_pair ( &*cur_entity , send_rank ) ); 00346 send_rank++; 00347 } 00348 cur_entity++; 00349 } 00350 cur_bucket++; 00351 } 00352 bulk.change_ghosting ( ghosting , to_send , empty_vector ); 00353 bulk.modification_end(); 00354 00355 { 00356 std::vector<stk::mesh::EntityProc> send_list ; 00357 std::vector<stk::mesh::Entity*> recv_list ; 00358 ghosting.send_list( send_list ); 00359 ghosting.receive_list( recv_list ); 00360 00361 STKUNIT_ASSERT ( ! send_list.empty() ); 00362 STKUNIT_ASSERT ( ! recv_list.empty() ); 00363 } 00364 00365 bulk.modification_begin(); 00366 bulk.destroy_all_ghosting (); 00367 bulk.modification_end(); 00368 00369 { 00370 std::vector<stk::mesh::EntityProc> send_list ; 00371 std::vector<stk::mesh::Entity*> recv_list ; 00372 ghosting.send_list( send_list ); 00373 ghosting.receive_list( recv_list ); 00374 00375 STKUNIT_ASSERT ( send_list.empty() ); 00376 STKUNIT_ASSERT ( recv_list.empty() ); 00377 } 00378 } 00379 00380 00381 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyChangeGhostingGuards ) 00382 { 00383 stk::unit_test::UnitTestMesh fixture1( MPI_COMM_WORLD ) , fixture2( MPI_COMM_WORLD ); 00384 stk::mesh::BulkData &bulk1 = fixture1.nonconst_bulk_data (); 00385 stk::mesh::BulkData &bulk2 = fixture2.nonconst_bulk_data (); 00386 00387 fixture1.generate_boxes(); 00388 fixture2.generate_boxes(); 00389 00390 bulk1.modification_begin(); 00391 bulk2.modification_begin(); 00392 00393 std::vector<stk::mesh::EntityProc> to_send; 00394 std::vector<stk::mesh::Entity *> empty_vector; 00395 std::vector<stk::mesh::Bucket *>::const_iterator cur_bucket = bulk1.buckets(3).begin(); 00396 unsigned send_rank = 0; 00397 while ( cur_bucket != bulk1.buckets(3).end() ) 00398 { 00399 stk::mesh::Bucket::iterator cur_entity = (*cur_bucket)->begin(); 00400 while ( cur_entity != (*cur_bucket)->end() ) 00401 { 00402 if ( cur_entity->owner_rank() == fixture1.comm_rank() ) 00403 { 00404 if ( send_rank == fixture1.comm_size() ) send_rank = 0; 00405 if ( send_rank != fixture1.comm_rank() ) 00406 to_send.push_back ( std::make_pair ( &*cur_entity , send_rank ) ); 00407 send_rank++; 00408 } 00409 cur_entity++; 00410 } 00411 cur_bucket++; 00412 } 00413 00414 stk::mesh::Ghosting &ghosting = bulk1.create_ghosting ( "Ghost 1" ); 00415 STKUNIT_ASSERT_THROW ( bulk2.change_ghosting ( ghosting , to_send , empty_vector ) , std::runtime_error ); 00416 STKUNIT_ASSERT_THROW ( bulk1.change_ghosting ( bulk1.shared_aura() , to_send , empty_vector ) , std::runtime_error ); 00417 00418 ghosting.receive_list(empty_vector); 00419 ghosting.send_list(to_send); 00420 00421 bulk1.modification_end(); 00422 bulk2.modification_end(); 00423 } 00424 00425 00426 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyOtherGhostingGuards ) 00427 { 00428 stk::unit_test::UnitTestMesh fixture( MPI_COMM_WORLD ); 00429 stk::mesh::BulkData &bulk = fixture.nonconst_bulk_data (); 00430 fixture.generate_boxes (); 00431 bulk.modification_begin(); 00432 00433 std::vector<stk::mesh::EntityProc> to_send_unowned; 00434 std::vector<stk::mesh::EntityProc> empty_send; 00435 std::vector<stk::mesh::Entity *> to_remove_not_ghosted; 00436 std::vector<stk::mesh::Entity *> empty_remove; 00437 std::vector<stk::mesh::Bucket *>::const_iterator cur_bucket = bulk.buckets(3).begin(); 00438 unsigned send_rank = 0; 00439 while ( cur_bucket != bulk.buckets(3).end() ) 00440 { 00441 stk::mesh::Bucket::iterator cur_entity = (*cur_bucket)->begin(); 00442 while ( cur_entity != (*cur_bucket)->end() ) 00443 { 00444 if ( cur_entity->owner_rank() != fixture.comm_rank() ) 00445 { 00446 if ( send_rank == fixture.comm_size() ) send_rank = 0; 00447 if ( send_rank != fixture.comm_rank() ) 00448 to_send_unowned.push_back ( std::make_pair ( &*cur_entity , send_rank ) ); 00449 send_rank++; 00450 } 00451 else 00452 { 00453 to_remove_not_ghosted.push_back ( &*cur_entity ); 00454 } 00455 cur_entity++; 00456 } 00457 cur_bucket++; 00458 } 00459 00460 stk::mesh::Ghosting &ghosting = bulk.create_ghosting ( "Ghost 1" ); 00461 if ( to_send_unowned.size() > 0 ) 00462 { 00463 STKUNIT_ASSERT_THROW ( bulk.change_ghosting ( ghosting , to_send_unowned , empty_remove ) , std::runtime_error ); 00464 } 00465 else 00466 { 00467 bulk.change_ghosting ( ghosting , to_send_unowned , empty_remove ); 00468 } 00469 00470 if ( to_remove_not_ghosted.size() > 0 ) 00471 { 00472 STKUNIT_ASSERT_THROW ( bulk.change_ghosting ( ghosting , empty_send , to_remove_not_ghosted ) , std::runtime_error ); 00473 } 00474 else 00475 { 00476 bulk.change_ghosting ( ghosting , empty_send , to_remove_not_ghosted ); 00477 } 00478 bulk.modification_end(); 00479 } 00480 00481 00482 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyPartsOnCreate ) 00483 { 00484 stk::unit_test::UnitTestMesh fixture( MPI_COMM_WORLD ); 00485 stk::mesh::BulkData & bulk = fixture.nonconst_bulk_data (); 00486 stk::mesh::Part & part_a = fixture.get_part_a_0 (); 00487 stk::mesh::Part & part_b = fixture.get_part_b_0 (); 00488 00489 stk::mesh::PartVector create_vector; 00490 create_vector.push_back ( &part_a ); 00491 00492 bulk.modification_begin(); 00493 00494 stk::mesh::Entity &node = bulk.declare_entity ( 0 , fixture.comm_rank()+1 ,create_vector ); 00495 bulk.modification_end(); 00496 00497 STKUNIT_ASSERT ( node.bucket().member ( part_a ) ); 00498 00499 bulk.modification_begin(); 00500 create_vector.push_back ( &part_b ); 00501 stk::mesh::Entity &node2 = bulk.declare_entity ( 0 , fixture.comm_size() + fixture.comm_rank() + 1 , create_vector ); 00502 bulk.modification_end(); 00503 00504 STKUNIT_ASSERT ( node2.bucket().member ( part_a ) ); 00505 STKUNIT_ASSERT ( node2.bucket().member ( part_b ) ); 00506 } 00507 00508 //---------------------------------------------------------------------- 00509 00510 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyBoxGhosting ) 00511 { 00512 const unsigned p_size = stk::parallel_machine_size( MPI_COMM_WORLD ); 00513 if ( 8 < p_size ) { return ; } 00514 00515 stk::mesh::fixtures::HexFixture fixture( MPI_COMM_WORLD, 2, 2, 2 ); 00516 fixture.meta_data.commit(); 00517 fixture.generate_mesh(); 00518 00519 for ( size_t iz = 0 ; iz < 3 ; ++iz ) { 00520 for ( size_t iy = 0 ; iy < 3 ; ++iy ) { 00521 for ( size_t ix = 0 ; ix < 3 ; ++ix ) { 00522 stk::mesh::Entity * const node = fixture.node(ix,iy,iz); 00523 STKUNIT_ASSERT( NULL != node ); 00524 if ( NULL != node ) { 00525 STKUNIT_ASSERT( fixture.node_id(ix,iy,iz) == node->identifier() ); 00526 stk::mesh::fixtures::HexFixture::Scalar * const node_coord = 00527 stk::mesh::field_data( fixture.coord_field , *node ); 00528 STKUNIT_ASSERT( node_coord != NULL ); 00529 } 00530 } 00531 } 00532 } 00533 00534 for ( size_t iz = 0 ; iz < 2 ; ++iz ) { 00535 for ( size_t iy = 0 ; iy < 2 ; ++iy ) { 00536 for ( size_t ix = 0 ; ix < 2 ; ++ix ) { 00537 stk::mesh::Entity * const elem = fixture.elem(ix,iy,iz); 00538 STKUNIT_ASSERT( NULL != elem ); 00539 if ( NULL != elem ) { 00540 stk::mesh::PairIterRelation elem_nodes = elem->relations(); 00541 STKUNIT_ASSERT_EQUAL( 8u , elem_nodes.size() ); 00542 stk::mesh::fixtures::HexFixture::Scalar ** const elem_node_coord = 00543 stk::mesh::field_data( fixture.coord_gather_field , *elem ); 00544 for ( size_t j = 0 ; j < elem_nodes.size() ; ++j ) { 00545 STKUNIT_ASSERT_EQUAL( j , elem_nodes[j].identifier() ); 00546 stk::mesh::fixtures::HexFixture::Scalar * const node_coord = 00547 stk::mesh::field_data( fixture.coord_field , *elem_nodes[j].entity() ); 00548 STKUNIT_ASSERT( node_coord == elem_node_coord[ elem_nodes[j].identifier() ] ); 00549 } 00550 if ( 8u == elem_nodes.size() ) { 00551 STKUNIT_ASSERT( elem_nodes[0].entity() == fixture.node(ix,iy,iz)); 00552 STKUNIT_ASSERT( elem_nodes[1].entity() == fixture.node(ix+1,iy,iz)); 00553 STKUNIT_ASSERT( elem_nodes[2].entity() == fixture.node(ix+1,iy,iz+1)); 00554 STKUNIT_ASSERT( elem_nodes[3].entity() == fixture.node(ix,iy,iz+1)); 00555 STKUNIT_ASSERT( elem_nodes[4].entity() == fixture.node(ix,iy+1,iz)); 00556 STKUNIT_ASSERT( elem_nodes[5].entity() == fixture.node(ix+1,iy+1,iz)); 00557 STKUNIT_ASSERT( elem_nodes[6].entity() == fixture.node(ix+1,iy+1,iz+1)); 00558 STKUNIT_ASSERT( elem_nodes[7].entity() == fixture.node(ix,iy+1,iz+1)); 00559 } 00560 } 00561 } 00562 } 00563 } 00564 } 00565 00566 00567 00568 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , testEntityComm ) 00569 { 00570 //Test on unpack_field_values in EntityComm.cpp 00571 //code based on ../base/BulkDataGhosting.cpp 00572 //Create a simple mesh. Add nodes one element and some parts. 00573 00574 const int spatial_dimension = 3; 00575 stk::mesh::MetaData meta ( stk::unit_test::get_entity_rank_names ( spatial_dimension ) ); 00576 stk::mesh::TopologicalMetaData top( meta, spatial_dimension ); 00577 00578 stk::mesh::Part & part_a = top.declare_part<shards::Tetrahedron<4> >( "block_a" ); 00579 stk::mesh::Part & part_b = top.declare_part<shards::Tetrahedron<4> >( "block_b" ); 00580 00581 stk::mesh::Part & part_a_0 = top.declare_part<shards::Node>( "block_a_0" ); 00582 00583 typedef stk::mesh::Field<double> ScalarFieldType; 00584 00585 ScalarFieldType & volume = 00586 meta.declare_field < ScalarFieldType > ( "volume" , 4 ); 00587 ScalarFieldType & temperature = 00588 meta.declare_field < ScalarFieldType > ( "temperature" , 4 ); 00589 stk::mesh::Part & universal = meta.universal_part (); 00590 put_field ( volume , 3 , universal ); 00591 put_field ( temperature , 3 , universal ); 00592 00593 00594 meta.commit(); 00595 00596 00597 stk::mesh::PartVector create_vector; 00598 stk::mesh::PartVector empty_vector; 00599 create_vector.push_back ( &part_a ); 00600 create_vector.push_back ( &part_b ); 00601 00602 00603 stk::mesh::BulkData bulk ( meta , MPI_COMM_WORLD , 100 ); 00604 00605 bulk.modification_begin(); 00606 00607 stk::mesh::Ghosting &ghosts = bulk.create_ghosting ( "Ghost 1" ); 00608 00609 unsigned size2 = stk::parallel_machine_size( MPI_COMM_WORLD ); 00610 unsigned rank_count2 = stk::parallel_machine_rank( MPI_COMM_WORLD ); 00611 int new_id2 = size2 + rank_count2; 00612 00613 stk::mesh::Entity &elem2 = bulk.declare_entity ( 3 , new_id2+1 ,create_vector ); 00614 STKUNIT_ASSERT_EQUAL( elem2.bucket().member ( part_a ), true ); 00615 00616 00617 unsigned size = stk::parallel_machine_size( MPI_COMM_WORLD ); 00618 unsigned rank_count = stk::parallel_machine_rank( MPI_COMM_WORLD ); 00619 00620 00621 int id_base = 0; 00622 for ( id_base = 0 ; id_base < 99 ; ++id_base ) 00623 { 00624 int new_id = size * id_base + rank_count; 00625 stk::mesh::Entity &new_node = bulk.declare_entity( 0 , new_id+1 , empty_vector ); 00626 STKUNIT_ASSERT_EQUAL( new_node.bucket().member ( part_a_0 ), false ); 00627 } 00628 00629 00630 //Create a bucket of nodes for sending 00631 00632 std::vector<stk::mesh::EntityProc> add_send; 00633 00634 const std::vector<stk::mesh::Bucket*> & buckets = bulk.buckets( 0 ); 00635 00636 std::vector<stk::mesh::Bucket*>::const_iterator cur_bucket; 00637 00638 cur_bucket = buckets.begin(); 00639 00640 00641 unsigned send_rank = 0; 00642 while ( cur_bucket != buckets.end() ) 00643 { 00644 stk::mesh::Bucket::iterator cur_entity = (*cur_bucket)->begin(); 00645 while ( cur_entity != (*cur_bucket)->end() ) 00646 { 00647 if ( cur_entity->owner_rank() == rank_count ) 00648 { 00649 if ( send_rank == size ) send_rank = 0; 00650 if ( send_rank != rank_count ) 00651 add_send.push_back ( std::make_pair ( &*cur_entity , send_rank ) ); 00652 send_rank++; 00653 } 00654 cur_entity++; 00655 } 00656 cur_bucket++; 00657 } 00658 00659 00660 std::set< stk::mesh::EntityProc , stk::mesh::EntityLess > new_send ; 00661 std::set< stk::mesh::Entity * , stk::mesh::EntityLess > new_recv ; 00662 00663 00664 // Keep the closure of the remaining received ghosts. 00665 // Working from highest-to-lowest key (rank entity type) 00666 // results in insertion of the transitive closure. 00667 // Insertion will not invalidate the associative container's iterator. 00668 00669 for ( std::set< stk::mesh::Entity * , stk::mesh::EntityLess >::iterator 00670 i = new_recv.end() ; i != new_recv.begin() ; ) { 00671 --i ; 00672 00673 const unsigned erank = (*i)->entity_rank(); 00674 00675 for ( stk::mesh::PairIterRelation 00676 irel = (*i)->relations(); ! irel.empty() ; ++irel ) { 00677 if ( irel->entity_rank() < erank && 00678 in_receive_ghost( ghosts , * irel->entity() ) ) { 00679 new_recv.insert( irel->entity() ); 00680 } 00681 } 00682 } 00683 00684 00685 00686 // Initialize the new_send from the new_recv 00687 new_comm_recv_to_send( bulk , new_recv , new_send ); 00688 00689 00690 //------------------------------------ 00691 // Add the specified entities and their closure to the send ghosting 00692 00693 00694 for ( std::vector< stk::mesh::EntityProc >::const_iterator 00695 i = add_send.begin() ; i != add_send.end() ; ++i ) { 00696 new_insert_transitive_closure( new_send , *i ); 00697 } 00698 00699 // Synchronize the send and receive list. 00700 // If the send list contains a not-owned entity 00701 // inform the owner and receiver to ad that entity 00702 // to their ghost send and receive lists. 00703 00704 new_comm_sync_send_recv( bulk , new_send , new_recv ); 00705 00706 00707 //------------------------------------ 00708 // Push newly ghosted entities to the receivers and update the comm list. 00709 // Unpacking must proceed in entity-rank order so that higher ranking 00710 // entities that have relations to lower ranking entities will have 00711 // the lower ranking entities unpacked first. The higher and lower 00712 // ranking entities may be owned by different processes, 00713 // as such unpacking must be performed in rank order. 00714 00715 //Start of CommAll section: 00716 { 00717 00718 stk::CommAll comm( MPI_COMM_WORLD ); 00719 00720 for ( std::set< stk::mesh::EntityProc , stk::mesh::EntityLess >::iterator 00721 j = new_send.begin(); j != new_send.end() ; ++j ) { 00722 stk::mesh::Entity & entity = * j->first ; 00723 if ( ! in_ghost( ghosts , entity , j->second ) ) { 00724 // Not already being sent , must send it. 00725 stk::CommBuffer & buf = comm.send_buffer( j->second ); 00726 buf.pack<unsigned>( entity.entity_rank() ); 00727 stk::mesh::pack_entity_info( buf , entity ); 00728 stk::mesh::pack_field_values( buf , entity ); 00729 } 00730 } 00731 00732 00733 comm.allocate_buffers( size / 4 ); 00734 00735 for ( std::set< stk::mesh::EntityProc , stk::mesh::EntityLess >::iterator 00736 j = new_send.begin(); j != new_send.end() ; ++j ) { 00737 stk::mesh::Entity & entity = * j->first ; 00738 if ( ! in_ghost( ghosts , entity , j->second ) ) { 00739 // Not already being sent , must send it. 00740 stk::CommBuffer & buf = comm.send_buffer( j->second ); 00741 buf.pack<unsigned>( entity.entity_rank() ); 00742 stk::mesh::pack_entity_info( buf , entity ); 00743 stk::mesh::pack_field_values( buf , entity ); 00744 00745 } 00746 } 00747 00748 00749 comm.communicate(); 00750 00751 std::ostringstream error_msg ; 00752 00753 for ( unsigned rank = 0 ; rank < rank_count ; ++rank ) { 00754 00755 for ( unsigned p = 0 ; p < size ; ++p ) { 00756 00757 stk::CommBuffer & buf = comm.recv_buffer(p); 00758 00759 while ( buf.remaining() ) { 00760 00761 // Only unpack if of the current entity rank. 00762 // If not the current entity rank, break the iteration 00763 // until a subsequent entity rank iteration. 00764 { 00765 unsigned this_rank = ~0u ; 00766 buf.peek<unsigned>( this_rank ); 00767 if ( this_rank != rank ) break ; 00768 00769 buf.unpack<unsigned>( this_rank ); 00770 } 00771 00772 // FIXME for Carol; the code below did not work with -np 4 00773 //STKUNIT_ASSERT_EQUAL( stk::mesh::unpack_field_values( buf , elem2 , error_msg ), false); 00774 //std::cout << "Error message for unpack_field_values = " << error_msg.str() << std::endl ; 00775 00776 } 00777 } 00778 00779 } 00780 }//end of CommAll section 00781 00782 bulk.modification_end (); 00783 00784 00785 } 00786 00787 00788 void new_insert_transitive_closure( std::set<stk::mesh::EntityProc,stk::mesh::EntityLess> & new_send , 00789 const stk::mesh::EntityProc & entry ) 00790 { 00791 // Do not insert if I can determine that this entity is already 00792 // owned or shared by the receiving processor. 00793 00794 if ( entry.second != entry.first->owner_rank() && 00795 ! in_shared( * entry.first , entry.second ) ) { 00796 00797 std::pair< std::set<stk::mesh::EntityProc,stk::mesh::EntityLess>::iterator , bool > 00798 result = new_send.insert( entry ); 00799 00800 if ( result.second ) { 00801 // A new insertion, must also insert the closure 00802 00803 const unsigned etype = entry.first->entity_rank(); 00804 stk::mesh::PairIterRelation irel = entry.first->relations(); 00805 00806 for ( ; ! irel.empty() ; ++irel ) { 00807 if ( irel->entity_rank() < etype ) { 00808 stk::mesh::EntityProc tmp( irel->entity() , entry.second ); 00809 new_insert_transitive_closure( new_send , tmp ); 00810 } 00811 } 00812 } 00813 } 00814 } 00815 00816 00817 // Synchronize the send list to the receive list. 00818 00819 void new_comm_sync_send_recv( 00820 stk::mesh::BulkData & mesh , 00821 std::set< stk::mesh::EntityProc , stk::mesh::EntityLess > & new_send , 00822 std::set< stk::mesh::Entity * , stk::mesh::EntityLess > & new_recv ) 00823 { 00824 static const char method[] = "stk::mesh::BulkData::change_ghosting" ; 00825 const unsigned parallel_rank = mesh.parallel_rank(); 00826 const unsigned parallel_size = mesh.parallel_size(); 00827 00828 stk::CommAll all( mesh.parallel() ); 00829 00830 // Communication sizing: 00831 00832 for ( std::set< stk::mesh::EntityProc , stk::mesh::EntityLess >::iterator 00833 i = new_send.begin() ; i != new_send.end() ; ++i ) { 00834 const unsigned owner = i->first->owner_rank(); 00835 all.send_buffer( i->second ).skip<stk::mesh::EntityKey>(2); 00836 if ( owner != parallel_rank ) { 00837 all.send_buffer( owner ).skip<stk::mesh::EntityKey>(2); 00838 } 00839 } 00840 00841 all.allocate_buffers( parallel_size / 4 , false /* Not symmetric */ ); 00842 00843 // Communication packing (with message content comments): 00844 for ( std::set< stk::mesh::EntityProc , stk::mesh::EntityLess >::iterator 00845 i = new_send.begin() ; i != new_send.end() ; ) { 00846 const unsigned owner = i->first->owner_rank(); 00847 00848 // Inform receiver of ghosting, the receiver does not own 00849 // and does not share this entity. 00850 // The ghost either already exists or is a to-be-done new ghost. 00851 // This status will be resolved on the final communication pass 00852 // when new ghosts are packed and sent. 00853 00854 const stk::mesh::EntityKey &entity_key = i->first->key(); 00855 const uint64_t &proc = i->second; 00856 00857 all.send_buffer( i->second ).pack(entity_key).pack(proc); 00858 00859 if ( owner != parallel_rank ) { 00860 // I am not the owner of this entity. 00861 // Inform the owner of this ghosting need. 00862 all.send_buffer( owner ).pack(entity_key).pack(proc); 00863 00864 // Erase it from my processor's ghosting responsibility: 00865 // The iterator passed to the erase method will be invalidated. 00866 std::set< stk::mesh::EntityProc , stk::mesh::EntityLess >::iterator jrem = i ; ++i ; 00867 new_send.erase( jrem ); 00868 } 00869 else { 00870 ++i ; 00871 } 00872 } 00873 00874 all.communicate(); 00875 00876 // Communication unpacking: 00877 for ( unsigned p = 0 ; p < parallel_size ; ++p ) { 00878 stk::CommBuffer & buf = all.recv_buffer(p); 00879 while ( buf.remaining() ) { 00880 00881 stk::mesh::EntityKey entity_key; 00882 uint64_t proc(0); 00883 00884 buf.unpack(entity_key).unpack(proc); 00885 00886 stk::mesh::Entity * const e = mesh.get_entity( entity_key ); 00887 00888 if ( parallel_rank != proc ) { 00889 // Receiving a ghosting need for an entity I own. 00890 // Add it to my send list. 00891 if ( e == NULL ) { 00892 throw std::logic_error( std::string(method) ); 00893 } 00894 stk::mesh::EntityProc tmp( e , proc ); 00895 new_send.insert( tmp ); 00896 } 00897 else if ( e != NULL ) { 00898 // I am the receiver for this ghost. 00899 // If I already have it add it to the receive list, 00900 // otherwise don't worry about it - I will receive 00901 // it in the final new-ghosting communication. 00902 new_recv.insert( e ); 00903 } 00904 } 00905 } 00906 } 00907 00908 void new_comm_recv_to_send( 00909 stk::mesh::BulkData & mesh , 00910 const std::set< stk::mesh::Entity * , stk::mesh::EntityLess > & new_recv , 00911 std::set< stk::mesh::EntityProc , stk::mesh::EntityLess > & new_send ) 00912 { 00913 static const char method[] = "stk::mesh::BulkData::change_ghosting" ; 00914 00915 const unsigned parallel_size = mesh.parallel_size(); 00916 00917 stk::CommAll all( mesh.parallel() ); 00918 00919 for ( std::set< stk::mesh::Entity * , stk::mesh::EntityLess >::const_iterator 00920 i = new_recv.begin() ; i != new_recv.end() ; ++i ) { 00921 const unsigned owner = (*i)->owner_rank(); 00922 all.send_buffer( owner ).skip<stk::mesh::EntityKey>(1); 00923 } 00924 00925 all.allocate_buffers( parallel_size / 4 , false /* Not symmetric */ ); 00926 00927 for ( std::set< stk::mesh::Entity * , stk::mesh::EntityLess >::const_iterator 00928 i = new_recv.begin() ; i != new_recv.end() ; ++i ) { 00929 const unsigned owner = (*i)->owner_rank(); 00930 const stk::mesh::EntityKey key = (*i)->key(); 00931 all.send_buffer( owner ).pack<stk::mesh::EntityKey>( & key , 1 ); 00932 } 00933 00934 all.communicate(); 00935 00936 for ( unsigned p = 0 ; p < parallel_size ; ++p ) { 00937 stk::CommBuffer & buf = all.recv_buffer(p); 00938 while ( buf.remaining() ) { 00939 stk::mesh::EntityKey key ; 00940 buf.unpack<stk::mesh::EntityKey>( & key , 1 ); 00941 stk::mesh::EntityProc tmp( mesh.get_entity( entity_rank(key), entity_id(key) , method ) , p ); 00942 new_send.insert( tmp ); 00943 } 00944 } 00945 } 00946 00947