Sierra Toolkit Version of the Day
UnitTestBulkData_new.cpp
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::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::mesh::EntityProc,stk::mesh::EntityLess> &  ,
00032            const stk::mesh::EntityProc & entry );
00033 void new_comm_sync_send_recv(
00034    stk::mesh::BulkData & mesh ,
00035    std::set< stk::mesh::EntityProc , stk::mesh::EntityLess > & new_send ,
00036    std::set< stk::mesh::Entity * , stk::mesh::EntityLess > & new_recv );
00037 
00038 void new_comm_recv_to_send(
00039   stk::mesh::BulkData & mesh ,
00040   const std::set< stk::mesh::Entity * , stk::mesh::EntityLess > & new_recv ,
00041         std::set< stk::mesh::EntityProc , stk::mesh::EntityLess > & new_send );
00042 
00048 class TestBoxFixture : public stk::mesh::fixtures::BoxFixture
00049 {
00050  public:
00051   TestBoxFixture(stk::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::mesh::BulkData         &bulk = fixture.bulk_data();
00126   stk::mesh::Part             &new_part = fixture.get_test_part ();
00127   stk::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::mesh::Entity  *cell_to_delete = NULL;
00139   stk::mesh::Entity  *cell_to_delete_copy = NULL;
00140   std::vector<stk::mesh::Bucket *>::const_iterator cur_bucket = bulk.buckets(3).begin();
00141   while ( cur_bucket != bulk.buckets(3).end() )
00142   {
00143     stk::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::mesh::BulkData         &bulk = fixture.bulk_data();
00171   stk::mesh::Part             &new_part = fixture.get_test_part ();
00172   stk::mesh::PartVector        add_part, empty_vector;
00173   add_part.push_back ( &new_part );
00174 
00175   stk::mesh::EntityKey bad_key1 ( 45 , 1 );  // Bad entity rank
00176   stk::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::ParallelMachine pm = MPI_COMM_WORLD;
00195   unsigned p_size = stk::parallel_machine_size(pm);
00196   unsigned p_rank = stk::parallel_machine_rank(pm);
00197 
00198   stk::mesh::fixtures::QuadFixture fixture(pm, 1 /*nx*/, p_size /*ny*/);
00199   fixture.m_fem_meta.commit();
00200   fixture.generate_mesh();
00201   stk::mesh::BulkData & bulk = fixture.m_bulk_data;
00202 
00203   stk::mesh::PartVector empty_vector;
00204 
00205   stk::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::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::mesh::BulkData     &bulk = fixture.bulk_data ();
00238   stk::mesh::PartVector    empty_vector;
00239   stk::mesh::PartVector    cell_part_vector;
00240 
00241   bulk.modification_begin();
00242 
00243   stk::mesh::Entity &new_cell = bulk.declare_entity ( 3 , fixture.comm_rank()+1 , empty_vector );
00244   stk::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::mesh::fixtures::BoxFixture fixture;
00264   stk::mesh::BulkData          &bulk = fixture.bulk_data();
00265   stk::mesh::PartVector         test_parts;
00266   stk::mesh::PartVector         out_parts;
00267   stk::mesh::PartVector         empty_vector;
00268 
00269   stk::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::mesh::BulkData            &bulk = fixture.bulk_data ();
00286 
00287   bulk.modification_begin();
00288   stk::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::mesh::BulkData            &bulk = fixture.bulk_data ();
00299   stk::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::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::mesh::BulkData             &bulk = fixture.bulk_data ();
00344   stk::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::mesh::Entity*>::const_iterator
00358         cur_entity =  bulk.entity_comm().begin();
00359         cur_entity != bulk.entity_comm().end() ; ++cur_entity ) {
00360     stk::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::mesh::PartVector() );
00364       }
00365     }
00366   }
00367 
00368   bulk.modification_end();
00369 
00370   for ( std::vector<stk::mesh::Entity*>::const_iterator
00371         cur_entity =  bulk.entity_comm().begin();
00372         cur_entity != bulk.entity_comm().end() ; ++cur_entity ) {
00373     stk::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::mesh::BulkData             &bulk = fixture.bulk_data ();
00384   stk::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::mesh::Entity &node = fixture.get_new_entity ( 0 , 1 );
00392   stk::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::mesh::PartVector () );
00397   bulk.change_entity_parts ( cell , create_cell_parts , stk::mesh::PartVector () );
00398   // Add node to cell part
00399   stk::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::mesh::BulkData           &bulk = fixture.bulk_data ();
00416   stk::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::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::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::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::mesh::Ghosting &ghosting = bulk.create_ghosting ( "Ghost 1" );
00476 
00477   // Find a cell owned by this process
00478   std::vector<stk::mesh::Bucket *>::const_iterator cur_bucket = bulk.buckets(3).begin();
00479   unsigned send_rank = 0;
00480 
00481   std::vector<stk::mesh::EntityProc>  to_send;
00482   std::vector<stk::mesh::Entity *>    empty_vector;
00483   while ( cur_bucket != bulk.buckets(3).end() )
00484   {
00485     stk::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::mesh::EntityProc> send_list ;
00505     std::vector<stk::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::mesh::EntityProc> send_list ;
00523     std::vector<stk::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::mesh::BulkData & bulk1 = fixture1.bulk_data ();
00537   stk::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::mesh::EntityProc>  to_send;
00555   std::vector<stk::mesh::Entity *>    empty_vector;
00556   std::vector<stk::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::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::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::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::mesh::EntityProc>  to_send_unowned;
00602   std::vector<stk::mesh::EntityProc>  empty_send;
00603   std::vector<stk::mesh::Entity *>    to_remove_not_ghosted;
00604   std::vector<stk::mesh::Entity *>    empty_remove;
00605   std::vector<stk::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::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::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::mesh::BulkData           & bulk = fixture.bulk_data ();
00654    stk::mesh::Part               & part_a = fixture.get_part_a_0 ();
00655    stk::mesh::Part               & part_b = fixture.get_part_b_0 ();
00656 
00657    stk::mesh::PartVector           create_vector;
00658    create_vector.push_back ( &part_a );
00659 
00660    bulk.modification_begin();
00661 
00662    stk::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::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::parallel_machine_size( MPI_COMM_WORLD );
00681   if ( 8 < p_size ) { return ; }
00682 
00683   stk::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::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::mesh::fixtures::HexFixture::Scalar * const node_coord =
00695       stk::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::mesh::Entity * const elem = fixture.elem(ix,iy,iz);
00705     STKUNIT_ASSERT( NULL != elem );
00706 
00707     stk::mesh::PairIterRelation elem_nodes = elem->relations();
00708     STKUNIT_ASSERT_EQUAL( 8u , elem_nodes.size() );
00709     stk::mesh::fixtures::HexFixture::Scalar ** const elem_node_coord =
00710       stk::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::mesh::fixtures::HexFixture::Scalar * const node_coord =
00714         stk::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::mesh::fem::FEMMetaData fem_meta;
00742   fem_meta.FEM_initialize(spatial_dimension, stk::mesh::fem::entity_rank_names ( spatial_dimension ));
00743 
00744   stk::mesh::fem::CellTopology tet_top(shards::getCellTopologyData<shards::Tetrahedron<4> >());
00745   stk::mesh::Part & part_a = fem_meta.declare_part( "block_a", tet_top );
00746   stk::mesh::Part & part_b = fem_meta.declare_part( "block_b", tet_top );
00747 
00748   stk::mesh::fem::CellTopology node_top(shards::getCellTopologyData<shards::Node>());
00749   stk::mesh::Part & part_a_0 = fem_meta.declare_part( "block_a_0", node_top );
00750 
00751   typedef stk::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::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::mesh::PartVector    create_vector;
00764   stk::mesh::PartVector    empty_vector;
00765   create_vector.push_back ( &part_a );
00766   create_vector.push_back ( &part_b );
00767 
00768   stk::mesh::MetaData & meta = stk::mesh::fem::FEMMetaData::get_meta_data(fem_meta);
00769   stk::mesh::BulkData bulk ( meta , MPI_COMM_WORLD , 100 );
00770 
00771   bulk.modification_begin();
00772 
00773   stk::mesh::Ghosting &ghosts = bulk.create_ghosting ( "Ghost 1" );
00774 
00775   unsigned size2 = stk::parallel_machine_size( MPI_COMM_WORLD );
00776   unsigned rank_count2 = stk::parallel_machine_rank( MPI_COMM_WORLD );
00777   int new_id2 = size2 + rank_count2;
00778 
00779   stk::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::parallel_machine_size( MPI_COMM_WORLD );
00783   unsigned rank_count = stk::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::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::mesh::EntityProc>  add_send;
00796 
00797   const std::vector<stk::mesh::Bucket*> & buckets = bulk.buckets( 0 );
00798 
00799   std::vector<stk::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::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::mesh::EntityProc , stk::mesh::EntityLess > new_send ;
00822   std::set< stk::mesh::Entity * ,   stk::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::mesh::Entity * , stk::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::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::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::CommAll comm( MPI_COMM_WORLD );
00873 
00874     for ( std::set< stk::mesh::EntityProc , stk::mesh::EntityLess >::iterator
00875           j = new_send.begin(); j != new_send.end() ; ++j ) {
00876           stk::mesh::Entity & entity = * j->first ;
00877       if ( ! in_ghost( ghosts , entity , j->second ) ) {
00878         // Not already being sent , must send it.
00879         stk::CommBuffer & buf = comm.send_buffer( j->second );
00880         buf.pack<unsigned>( entity.entity_rank() );
00881         stk::mesh::pack_entity_info(  buf , entity );
00882         stk::mesh::pack_field_values( buf , entity );
00883       }
00884     }
00885 
00886     comm.allocate_buffers( size / 4 );
00887 
00888     for ( std::set< stk::mesh::EntityProc , stk::mesh::EntityLess >::iterator
00889           j = new_send.begin(); j != new_send.end() ; ++j ) {
00890           stk::mesh::Entity & entity = * j->first ;
00891       if ( ! in_ghost( ghosts , entity , j->second ) ) {
00892         // Not already being sent , must send it.
00893         stk::CommBuffer & buf = comm.send_buffer( j->second );
00894         buf.pack<unsigned>( entity.entity_rank() );
00895         stk::mesh::pack_entity_info(  buf , entity );
00896         stk::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::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::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::ParallelMachine pm = MPI_COMM_WORLD;
00940 
00941   stk::mesh::MetaData meta; // Construct, but do not initialize
00942   stk::mesh::BulkData bulk(meta, pm);
00943 
00944   meta.set_entity_rank_names(stk::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::mesh::PartVector() ),
00953                         std::logic_error);
00954 }
00955 
00956 namespace {
00957 
00958 void new_insert_transitive_closure( std::set<stk::mesh::EntityProc,stk::mesh::EntityLess> & new_send ,
00959                                 const stk::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::mesh::EntityProc,stk::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::mesh::PairIterRelation irel  = entry.first->relations();
00975 
00976       for ( ; ! irel.empty() ; ++irel ) {
00977         if ( irel->entity_rank() < etype ) {
00978           stk::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::mesh::BulkData & mesh ,
00991   std::set< stk::mesh::EntityProc , stk::mesh::EntityLess > & new_send ,
00992   std::set< stk::mesh::Entity * , stk::mesh::EntityLess > & new_recv )
00993 {
00994   const unsigned parallel_rank = mesh.parallel_rank();
00995   const unsigned parallel_size = mesh.parallel_size();
00996 
00997   stk::CommAll all( mesh.parallel() );
00998 
00999   // Communication sizing:
01000 
01001   for ( std::set< stk::mesh::EntityProc , stk::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::mesh::EntityKey>(2);
01005     if ( owner != parallel_rank ) {
01006       all.send_buffer( owner ).skip<stk::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::mesh::EntityProc , stk::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::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::mesh::EntityProc , stk::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::CommBuffer & buf = all.recv_buffer(p);
01048     while ( buf.remaining() ) {
01049 
01050       stk::mesh::EntityKey entity_key;
01051       uint64_t proc(0);
01052 
01053       buf.unpack(entity_key).unpack(proc);
01054 
01055       stk::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::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::mesh::BulkData & mesh ,
01077   const std::set< stk::mesh::Entity * , stk::mesh::EntityLess > & new_recv ,
01078         std::set< stk::mesh::EntityProc , stk::mesh::EntityLess > & new_send )
01079 {
01080   const unsigned parallel_size = mesh.parallel_size();
01081 
01082   stk::CommAll all( mesh.parallel() );
01083 
01084   for ( std::set< stk::mesh::Entity * , stk::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::mesh::EntityKey>(1);
01088   }
01089 
01090   all.allocate_buffers( parallel_size / 4 , false /* Not symmetric */ );
01091 
01092   for ( std::set< stk::mesh::Entity * , stk::mesh::EntityLess >::const_iterator
01093         i = new_recv.begin() ; i != new_recv.end() ; ++i ) {
01094     const unsigned owner = (*i)->owner_rank();
01095     const stk::mesh::EntityKey key = (*i)->key();
01096     all.send_buffer( owner ).pack<stk::mesh::EntityKey>( & key , 1 );
01097   }
01098 
01099   all.communicate();
01100 
01101   for ( unsigned p = 0 ; p < parallel_size ; ++p ) {
01102     stk::CommBuffer & buf = all.recv_buffer(p);
01103     while ( buf.remaining() ) {
01104       stk::mesh::EntityKey key ;
01105       buf.unpack<stk::mesh::EntityKey>( & key , 1 );
01106       stk::mesh::EntityProc tmp( mesh.get_entity( entity_rank(key), entity_id(key) ) , p );
01107       new_send.insert( tmp );
01108     }
01109   }
01110 }
01111 
01112 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines