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