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   STKUNIT_ASSERT_THROW ( bulk.change_entity_parts ( new_node , cell_part_vector ) , std::runtime_error );
00251 }
00252 
00253 /************************
00254  * This unit test is not possible currently because of the lack of
00255  * separation between internal part modification routines and public
00256  * part modification routines.
00257 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyCannotRemoveFromSpecialParts )
00258 {
00259   stk::mesh::fixtures::BoxFixture fixture;
00260   stk::mesh::BulkData          &bulk = fixture.bulk_data();
00261   stk::mesh::PartVector         test_parts;
00262   stk::mesh::PartVector         out_parts;
00263   stk::mesh::PartVector         empty_vector;
00264 
00265   stk::mesh::Entity &new_cell = bulk.declare_entity ( 3 , fixture.comm_rank()+1 , empty_vector );
00266   test_parts.push_back ( &fixture.fem_meta().universal_part() );
00267   STKUNIT_ASSERT_THROW ( bulk.change_entity_parts ( new_cell , empty_vector , test_parts ) , std::runtime_error );
00268   test_parts.clear();
00269   test_parts.push_back ( &fixture.fem_meta().locally_owned_part() );
00270   STKUNIT_ASSERT_THROW ( bulk.change_entity_parts ( new_cell , empty_vector , test_parts ) , std::runtime_error );
00271   test_parts.clear();
00272   test_parts.push_back ( &fixture.fem_meta().globally_shared_part() );
00273   STKUNIT_ASSERT_THROW ( bulk.change_entity_parts ( new_cell , empty_vector , test_parts ) , std::runtime_error );
00274 }
00275  */
00276 
00277 
00278 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyDefaultPartAddition )
00279 {
00280   TestBoxFixture fixture;
00281   stk::mesh::BulkData            &bulk = fixture.bulk_data ();
00282 
00283   bulk.modification_begin();
00284   stk::mesh::Entity &new_cell = fixture.get_new_entity ( 3 , 1 );
00285   bulk.modification_end();
00286 
00287   STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.fem_meta().universal_part() ) );
00288   STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.fem_meta().locally_owned_part() ) );
00289 }
00290 
00291 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyChangePartsSerial )
00292 {
00293   TestBoxFixture fixture;
00294   stk::mesh::BulkData            &bulk = fixture.bulk_data ();
00295   stk::mesh::PartVector           create_parts , remove_parts , add_parts, empty_parts;
00296 
00297   create_parts.push_back ( &fixture.get_test_part() );
00298   create_parts.push_back ( &fixture.get_part_a_3() );
00299   remove_parts.push_back ( &fixture.get_part_a_3() );
00300   add_parts.push_back ( &fixture.get_part_b_superset() );
00301   add_parts.push_back ( &fixture.get_cell_part() );
00302 
00303   bulk.modification_begin();
00304   stk::mesh::Entity &new_cell = fixture.get_new_entity ( 3 , 1 );
00305   bulk.change_entity_parts ( new_cell , create_parts , empty_parts );
00306   bulk.modification_end();
00307   STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_test_part() ) );
00308   STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_part_a_3() ) );
00309   STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_part_a_superset() ) );
00310   STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_part_b_superset() ) );
00311   STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_cell_part() ) );
00312 
00313   bulk.modification_begin();
00314   bulk.change_entity_parts ( new_cell , add_parts , remove_parts );
00315   bulk.modification_end();
00316   STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_test_part() ) );
00317   STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_part_a_3() ) );
00318   STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_part_a_superset() ) );
00319   STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_part_b_superset() ) );
00320   STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_cell_part() ) );
00321 
00322   bulk.modification_begin();
00323   bulk.change_entity_parts ( new_cell , empty_parts , add_parts );
00324   bulk.modification_end();
00325   STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_test_part() ) );
00326   STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_part_a_3() ) );
00327   STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_part_a_superset() ) );
00328   STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_part_b_superset() ) );
00329   STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_cell_part() ) );
00330 
00331   //Verify still a member of default parts
00332   STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.fem_meta().universal_part() ) );
00333   STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.fem_meta().locally_owned_part() ) );
00334 }
00335 
00336 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyParallelAddParts )
00337 {
00338   TestBoxFixture fixture;
00339   stk::mesh::BulkData             &bulk = fixture.bulk_data ();
00340   stk::mesh::PartVector            add_part;
00341 
00342   const int root_box[3][2] = { { 0 , 4 } , { 0 , 5 } , { 0 , 6 } };
00343   int local_box[3][2] = { { 0 , 0 } , { 0 , 0 } , { 0 , 0 } };
00344 
00345   add_part.push_back ( &fixture.get_part_a_0() );
00346 
00347   bulk.modification_begin();
00348   fixture.generate_boxes( root_box, local_box );
00349   STKUNIT_ASSERT(bulk.modification_end());
00350 
00351   bulk.modification_begin();
00352 
00353   for ( std::vector<stk::mesh::Entity*>::const_iterator
00354         cur_entity =  bulk.entity_comm().begin();
00355         cur_entity != bulk.entity_comm().end() ; ++cur_entity ) {
00356     stk::mesh::Entity & entity = **cur_entity ;
00357     if ( entity.entity_rank() == 0 ) {
00358       if ( entity.owner_rank() == fixture.comm_rank() ) {
00359         bulk.change_entity_parts ( entity, add_part, stk::mesh::PartVector() );
00360       }
00361     }
00362   }
00363 
00364   bulk.modification_end();
00365 
00366   for ( std::vector<stk::mesh::Entity*>::const_iterator
00367         cur_entity =  bulk.entity_comm().begin();
00368         cur_entity != bulk.entity_comm().end() ; ++cur_entity ) {
00369     stk::mesh::Entity & entity = **cur_entity ;
00370     if ( entity.entity_rank() == 0 ) {
00371       STKUNIT_ASSERT ( entity.bucket().member ( fixture.get_part_a_0 () ) );
00372     }
00373   }
00374 }
00375 
00376 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyInducedMembership )
00377 {
00378   TestBoxFixture fixture;
00379   stk::mesh::BulkData             &bulk = fixture.bulk_data ();
00380   stk::mesh::PartVector            create_node_parts , create_cell_parts , empty_parts;
00381 
00382   create_node_parts.push_back ( &fixture.get_part_a_0() );
00383   create_cell_parts.push_back ( &fixture.get_cell_part() );
00384 
00385   bulk.modification_begin();
00386 
00387   stk::mesh::Entity &node = fixture.get_new_entity ( 0 , 1 );
00388   stk::mesh::Entity &cell = fixture.get_new_entity ( 3 , 1 );
00389 
00390   bulk.modification_begin();
00391 
00392   bulk.change_entity_parts ( node , create_node_parts , stk::mesh::PartVector () );
00393   bulk.change_entity_parts ( cell , create_cell_parts , stk::mesh::PartVector () );
00394   // Add node to cell part
00395   stk::mesh::RelationIdentifier cell_node_rel_id = 0;
00396   bulk.declare_relation ( cell , node , cell_node_rel_id );
00397   bulk.modification_end();
00398 
00399   STKUNIT_ASSERT ( node.bucket().member ( fixture.get_cell_part() ) );
00400 
00401   bulk.modification_begin();
00402   bulk.destroy_relation ( cell , node, cell_node_rel_id );
00403   bulk.modification_end();
00404 
00405   STKUNIT_ASSERT ( !node.bucket().member ( fixture.get_cell_part() ) );
00406 }
00407 
00408 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyCanRemoveFromSetWithDifferentRankSubset )
00409 {
00410   TestBoxFixture fixture;
00411   stk::mesh::BulkData           &bulk = fixture.bulk_data ();
00412   stk::mesh::PartVector          add_parts , remove_parts, empty_parts;
00413 
00414   add_parts.push_back ( &fixture.get_part_b_3() );
00415   add_parts.push_back ( &fixture.get_part_a_superset() );
00416 
00417   remove_parts.push_back ( &fixture.get_part_a_superset() );
00418 
00419   bulk.modification_begin();
00420 
00421   stk::mesh::Entity  &e = bulk.declare_entity ( 3 , fixture.comm_rank()+1 , add_parts );
00422   bulk.modification_end();
00423 
00424   bulk.modification_begin();
00425   bulk.change_entity_parts ( e , empty_parts , remove_parts );
00426   bulk.modification_end();
00427 
00428   STKUNIT_ASSERT ( e.bucket().member ( fixture.get_part_b_3() ) );
00429   STKUNIT_ASSERT ( !e.bucket().member ( fixture.get_part_a_superset() ) );
00430 }
00431 
00432 
00433 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyCommonGhostingName )
00434 {
00435 
00436   TestBoxFixture fixture;
00437   stk::mesh::BulkData          &bulk = fixture.bulk_data ();
00438 
00439   bulk.modification_begin();
00440 
00441   if ( fixture.comm_size() == 1 ) return;
00442 
00443   if ( fixture.comm_rank() == 0 )
00444   {
00445     STKUNIT_ASSERT_THROW ( bulk.create_ghosting ( "Name 1" ) , std::runtime_error );
00446   }
00447   else
00448   {
00449     STKUNIT_ASSERT_THROW ( bulk.create_ghosting ( "Name 2" ) , std::runtime_error );
00450   }
00451 }
00452 
00453 
00454 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyTrivialDestroyAllGhostings )
00455 {
00456   TestBoxFixture fixture;
00457 
00458   if ( fixture.comm_size() == 1 ) return;
00459 
00460   stk::mesh::BulkData  &bulk = fixture.bulk_data();
00461 
00462   const int root_box[3][2] = { { 0 , 4 } , { 0 , 5 } , { 0 , 6 } };
00463   int local_box[3][2] = { { 0 , 0 } , { 0 , 0 } , { 0 , 0 } };
00464 
00465   bulk.modification_begin();
00466   fixture.generate_boxes( root_box, local_box );
00467   STKUNIT_ASSERT(bulk.modification_end());
00468 
00469   bulk.modification_begin();
00470 
00471   stk::mesh::Ghosting &ghosting = bulk.create_ghosting ( "Ghost 1" );
00472 
00473   // Find a cell owned by this process
00474   std::vector<stk::mesh::Bucket *>::const_iterator cur_bucket = bulk.buckets(3).begin();
00475   unsigned send_rank = 0;
00476 
00477   std::vector<stk::mesh::EntityProc>  to_send;
00478   std::vector<stk::mesh::Entity *>    empty_vector;
00479   while ( cur_bucket != bulk.buckets(3).end() )
00480   {
00481     stk::mesh::Bucket::iterator cur_entity = (*cur_bucket)->begin();
00482     while ( cur_entity != (*cur_bucket)->end() )
00483     {
00484       if ( cur_entity->owner_rank() == fixture.comm_rank() )
00485       {
00486         if ( send_rank == fixture.comm_size() ) send_rank = 0;
00487         if ( send_rank != fixture.comm_rank() )
00488           to_send.push_back ( std::make_pair ( &*cur_entity , send_rank ) );
00489         send_rank++;
00490       }
00491       cur_entity++;
00492     }
00493     cur_bucket++;
00494   }
00495   bulk.change_ghosting ( ghosting , to_send , empty_vector );
00496   bulk.modification_end();
00497 
00498 
00499   {
00500     std::vector<stk::mesh::EntityProc> send_list ;
00501     std::vector<stk::mesh::Entity*>    recv_list ;
00502     ghosting.send_list( send_list );
00503     ghosting.receive_list( recv_list );
00504 
00505     STKUNIT_ASSERT ( ! send_list.empty()  );
00506     STKUNIT_ASSERT ( ! recv_list.empty() );
00507   }
00508 
00509   // Usage of operator << in Ghosting.cpp
00510   std::ostringstream oss;
00511   oss << ghosting;
00512 
00513   bulk.modification_begin();
00514   bulk.destroy_all_ghosting ();
00515   bulk.modification_end();
00516 
00517   {
00518     std::vector<stk::mesh::EntityProc> send_list ;
00519     std::vector<stk::mesh::Entity*>    recv_list ;
00520     ghosting.send_list( send_list );
00521     ghosting.receive_list( recv_list );
00522 
00523     STKUNIT_ASSERT ( send_list.empty() );
00524     STKUNIT_ASSERT ( recv_list.empty() );
00525   }
00526 }
00527 
00528 
00529 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyChangeGhostingGuards )
00530 {
00531   TestBoxFixture fixture1, fixture2;
00532   stk::mesh::BulkData & bulk1 = fixture1.bulk_data ();
00533   stk::mesh::BulkData & bulk2 = fixture2.bulk_data ();
00534 
00535   const int root_box[3][2] = { { 0 , 4 } , { 0 , 5 } , { 0 , 6 } };
00536   int local_box1[3][2] = { { 0 , 0 } , { 0 , 0 } , { 0 , 0 } };
00537   int local_box2[3][2] = { { 0 , 0 } , { 0 , 0 } , { 0 , 0 } };
00538 
00539   bulk1.modification_begin();
00540   fixture1.generate_boxes( root_box, local_box1 );
00541   STKUNIT_ASSERT(bulk1.modification_end());
00542 
00543   bulk2.modification_begin();
00544   fixture2.generate_boxes( root_box, local_box2 );
00545   STKUNIT_ASSERT(bulk2.modification_end());
00546 
00547   bulk1.modification_begin();
00548   bulk2.modification_begin();
00549 
00550   std::vector<stk::mesh::EntityProc>  to_send;
00551   std::vector<stk::mesh::Entity *>    empty_vector;
00552   std::vector<stk::mesh::Bucket *>::const_iterator cur_bucket = bulk1.buckets(3).begin();
00553   unsigned send_rank = 0;
00554   while ( cur_bucket != bulk1.buckets(3).end() )
00555   {
00556     stk::mesh::Bucket::iterator cur_entity = (*cur_bucket)->begin();
00557     while ( cur_entity != (*cur_bucket)->end() )
00558     {
00559       if ( cur_entity->owner_rank() == fixture1.comm_rank() )
00560       {
00561         if ( send_rank == fixture1.comm_size() ) send_rank = 0;
00562         if ( send_rank != fixture1.comm_rank() )
00563           to_send.push_back ( std::make_pair ( &*cur_entity , send_rank ) );
00564         send_rank++;
00565       }
00566       cur_entity++;
00567     }
00568     cur_bucket++;
00569   }
00570 
00571   stk::mesh::Ghosting &ghosting = bulk1.create_ghosting ( "Ghost 1" );
00572   STKUNIT_ASSERT_THROW ( bulk2.change_ghosting ( ghosting , to_send , empty_vector ) , std::runtime_error );
00573   STKUNIT_ASSERT_THROW ( bulk1.change_ghosting ( bulk1.shared_aura() , to_send , empty_vector ) , std::runtime_error );
00574 
00575   ghosting.receive_list(empty_vector);
00576   ghosting.send_list(to_send);
00577 
00578   bulk1.modification_end();
00579   bulk2.modification_end();
00580 }
00581 
00582 
00583 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyOtherGhostingGuards )
00584 {
00585   TestBoxFixture fixture;
00586   stk::mesh::BulkData          &bulk = fixture.bulk_data ();
00587 
00588   const int root_box[3][2] = { { 0 , 4 } , { 0 , 5 } , { 0 , 6 } };
00589   int local_box[3][2] = { { 0 , 0 } , { 0 , 0 } , { 0 , 0 } };
00590 
00591   bulk.modification_begin();
00592   fixture.generate_boxes( root_box, local_box );
00593   STKUNIT_ASSERT(bulk.modification_end());
00594 
00595   bulk.modification_begin();
00596 
00597   std::vector<stk::mesh::EntityProc>  to_send_unowned;
00598   std::vector<stk::mesh::EntityProc>  empty_send;
00599   std::vector<stk::mesh::Entity *>    to_remove_not_ghosted;
00600   std::vector<stk::mesh::Entity *>    empty_remove;
00601   std::vector<stk::mesh::Bucket *>::const_iterator cur_bucket = bulk.buckets(3).begin();
00602   unsigned send_rank = 0;
00603   while ( cur_bucket != bulk.buckets(3).end() )
00604   {
00605     stk::mesh::Bucket::iterator cur_entity = (*cur_bucket)->begin();
00606     while ( cur_entity != (*cur_bucket)->end() )
00607     {
00608       if ( cur_entity->owner_rank() != fixture.comm_rank() )
00609       {
00610         if ( send_rank == fixture.comm_size() ) send_rank = 0;
00611         if ( send_rank != fixture.comm_rank() )
00612           to_send_unowned.push_back ( std::make_pair ( &*cur_entity , send_rank ) );
00613         send_rank++;
00614       }
00615       else
00616       {
00617         to_remove_not_ghosted.push_back ( &*cur_entity );
00618       }
00619       cur_entity++;
00620     }
00621     cur_bucket++;
00622   }
00623 
00624   stk::mesh::Ghosting &ghosting = bulk.create_ghosting ( "Ghost 1" );
00625   if ( to_send_unowned.size() > 0 )
00626   {
00627     STKUNIT_ASSERT_THROW ( bulk.change_ghosting ( ghosting , to_send_unowned , empty_remove ) , std::runtime_error );
00628   }
00629   else
00630   {
00631     bulk.change_ghosting ( ghosting , to_send_unowned , empty_remove );
00632   }
00633 
00634   if ( to_remove_not_ghosted.size() > 0 )
00635   {
00636     STKUNIT_ASSERT_THROW ( bulk.change_ghosting ( ghosting , empty_send , to_remove_not_ghosted ) , std::runtime_error );
00637   }
00638   else
00639   {
00640     bulk.change_ghosting ( ghosting , empty_send , to_remove_not_ghosted );
00641   }
00642   bulk.modification_end();
00643 }
00644 
00645 
00646 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyPartsOnCreate )
00647 {
00648    TestBoxFixture fixture;
00649    stk::mesh::BulkData           & bulk = fixture.bulk_data ();
00650    stk::mesh::Part               & part_a = fixture.get_part_a_0 ();
00651    stk::mesh::Part               & part_b = fixture.get_part_b_0 ();
00652 
00653    stk::mesh::PartVector           create_vector;
00654    create_vector.push_back ( &part_a );
00655 
00656    bulk.modification_begin();
00657 
00658    stk::mesh::Entity &node = bulk.declare_entity ( 0 , fixture.comm_rank()+1 ,create_vector );
00659    bulk.modification_end();
00660 
00661    STKUNIT_ASSERT ( node.bucket().member ( part_a ) );
00662 
00663    bulk.modification_begin();
00664    create_vector.push_back ( &part_b );
00665    stk::mesh::Entity &node2 = bulk.declare_entity ( 0 , fixture.comm_size() + fixture.comm_rank() + 1 , create_vector );
00666    bulk.modification_end();
00667 
00668    STKUNIT_ASSERT ( node2.bucket().member ( part_a ) );
00669    STKUNIT_ASSERT ( node2.bucket().member ( part_b ) );
00670 }
00671 
00672 //----------------------------------------------------------------------
00673 
00674 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyBoxGhosting )
00675 {
00676   const unsigned p_size = stk::parallel_machine_size( MPI_COMM_WORLD );
00677   if ( 8 < p_size ) { return ; }
00678 
00679   stk::mesh::fixtures::HexFixture fixture( MPI_COMM_WORLD, 2, 2, 2 );
00680   fixture.m_fem_meta.commit();
00681   fixture.generate_mesh();
00682 
00683   for ( size_t iz = 0 ; iz < 3 ; ++iz ) {
00684   for ( size_t iy = 0 ; iy < 3 ; ++iy ) {
00685   for ( size_t ix = 0 ; ix < 3 ; ++ix ) {
00686     stk::mesh::Entity * const node = fixture.node(ix,iy,iz);
00687     STKUNIT_ASSERT( NULL != node );
00688     if ( NULL != node ) {
00689       STKUNIT_ASSERT( fixture.node_id(ix,iy,iz) == node->identifier() );
00690       stk::mesh::fixtures::HexFixture::Scalar * const node_coord =
00691         stk::mesh::field_data( fixture.m_coord_field , *node );
00692       STKUNIT_ASSERT( node_coord != NULL );
00693     }
00694   }
00695   }
00696   }
00697 
00698   for ( size_t iz = 0 ; iz < 2 ; ++iz ) {
00699   for ( size_t iy = 0 ; iy < 2 ; ++iy ) {
00700   for ( size_t ix = 0 ; ix < 2 ; ++ix ) {
00701     stk::mesh::Entity * const elem = fixture.elem(ix,iy,iz);
00702     STKUNIT_ASSERT( NULL != elem );
00703     if ( NULL != elem ) {
00704       stk::mesh::PairIterRelation elem_nodes = elem->relations();
00705       STKUNIT_ASSERT_EQUAL( 8u , elem_nodes.size() );
00706       stk::mesh::fixtures::HexFixture::Scalar ** const elem_node_coord =
00707         stk::mesh::field_data( fixture.m_coord_gather_field , *elem );
00708       for ( size_t j = 0 ; j < elem_nodes.size() ; ++j ) {
00709         STKUNIT_ASSERT_EQUAL( j , elem_nodes[j].identifier() );
00710         stk::mesh::fixtures::HexFixture::Scalar * const node_coord =
00711           stk::mesh::field_data( fixture.m_coord_field , *elem_nodes[j].entity() );
00712         STKUNIT_ASSERT( node_coord == elem_node_coord[ elem_nodes[j].identifier() ] );
00713       }
00714       if ( 8u == elem_nodes.size() ) {
00715         STKUNIT_ASSERT( elem_nodes[0].entity() == fixture.node(ix,iy,iz));
00716         STKUNIT_ASSERT( elem_nodes[1].entity() == fixture.node(ix+1,iy,iz));
00717         STKUNIT_ASSERT( elem_nodes[2].entity() == fixture.node(ix+1,iy,iz+1));
00718         STKUNIT_ASSERT( elem_nodes[3].entity() == fixture.node(ix,iy,iz+1));
00719         STKUNIT_ASSERT( elem_nodes[4].entity() == fixture.node(ix,iy+1,iz));
00720         STKUNIT_ASSERT( elem_nodes[5].entity() == fixture.node(ix+1,iy+1,iz));
00721         STKUNIT_ASSERT( elem_nodes[6].entity() == fixture.node(ix+1,iy+1,iz+1));
00722         STKUNIT_ASSERT( elem_nodes[7].entity() == fixture.node(ix,iy+1,iz+1));
00723       }
00724     }
00725   }
00726   }
00727   }
00728 }
00729 
00730 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , testEntityComm )
00731 {
00732   //Test on unpack_field_values in EntityComm.cpp
00733   //code based on ../base/BulkDataGhosting.cpp
00734   //Create a simple mesh. Add nodes one element and some parts.
00735 
00736   const int spatial_dimension = 3;
00737 
00738   stk::mesh::fem::FEMMetaData fem_meta;
00739   fem_meta.FEM_initialize(spatial_dimension, stk::mesh::fem::entity_rank_names ( spatial_dimension ));
00740 
00741   stk::mesh::fem::CellTopology tet_top(shards::getCellTopologyData<shards::Tetrahedron<4> >());
00742   stk::mesh::Part & part_a = fem_meta.declare_part( "block_a", tet_top );
00743   stk::mesh::Part & part_b = fem_meta.declare_part( "block_b", tet_top );
00744 
00745   stk::mesh::fem::CellTopology node_top(shards::getCellTopologyData<shards::Node>());
00746   stk::mesh::Part & part_a_0 = fem_meta.declare_part( "block_a_0", node_top );
00747 
00748   typedef stk::mesh::Field<double>  ScalarFieldType;
00749 
00750   ScalarFieldType & volume =
00751      fem_meta.declare_field < ScalarFieldType > ( "volume" , 4 );
00752   ScalarFieldType & temperature =
00753      fem_meta.declare_field < ScalarFieldType > ( "temperature" , 4 );
00754   stk::mesh::Part  & universal     = fem_meta.universal_part ();
00755   put_field ( volume , 3 , universal );
00756   put_field ( temperature , 3 , universal );
00757 
00758   fem_meta.commit();
00759 
00760   stk::mesh::PartVector    create_vector;
00761   stk::mesh::PartVector    empty_vector;
00762   create_vector.push_back ( &part_a );
00763   create_vector.push_back ( &part_b );
00764 
00765   stk::mesh::MetaData & meta = stk::mesh::fem::FEMMetaData::get_meta_data(fem_meta);
00766   stk::mesh::BulkData bulk ( meta , MPI_COMM_WORLD , 100 );
00767 
00768   bulk.modification_begin();
00769 
00770   stk::mesh::Ghosting &ghosts = bulk.create_ghosting ( "Ghost 1" );
00771 
00772   unsigned size2 = stk::parallel_machine_size( MPI_COMM_WORLD );
00773   unsigned rank_count2 = stk::parallel_machine_rank( MPI_COMM_WORLD );
00774   int new_id2 = size2 + rank_count2;
00775 
00776   stk::mesh::Entity &elem2 = bulk.declare_entity ( 3 , new_id2+1 ,create_vector );
00777   STKUNIT_ASSERT_EQUAL( elem2.bucket().member ( part_a ), true );
00778 
00779   unsigned size = stk::parallel_machine_size( MPI_COMM_WORLD );
00780   unsigned rank_count = stk::parallel_machine_rank( MPI_COMM_WORLD );
00781 
00782   int id_base = 0;
00783   for ( id_base = 0 ; id_base < 99 ; ++id_base )
00784   {
00785     int new_id = size * id_base + rank_count;
00786     stk::mesh::Entity &new_node = bulk.declare_entity( 0 , new_id+1 , empty_vector );
00787     STKUNIT_ASSERT_EQUAL( new_node.bucket().member ( part_a_0 ), false );
00788   }
00789 
00790   //Create a bucket of nodes for sending
00791 
00792   std::vector<stk::mesh::EntityProc>  add_send;
00793 
00794   const std::vector<stk::mesh::Bucket*> & buckets = bulk.buckets( 0 );
00795 
00796   std::vector<stk::mesh::Bucket*>::const_iterator cur_bucket;
00797 
00798   cur_bucket = buckets.begin();
00799 
00800   unsigned send_rank = 0;
00801   while ( cur_bucket != buckets.end() )
00802   {
00803     stk::mesh::Bucket::iterator cur_entity = (*cur_bucket)->begin();
00804     while ( cur_entity != (*cur_bucket)->end() )
00805     {
00806       if ( cur_entity->owner_rank() == rank_count )
00807       {
00808         if ( send_rank == size ) send_rank = 0;
00809         if ( send_rank != rank_count )
00810           add_send.push_back ( std::make_pair ( &*cur_entity , send_rank ) );
00811         send_rank++;
00812       }
00813       cur_entity++;
00814     }
00815     cur_bucket++;
00816   }
00817 
00818   std::set< stk::mesh::EntityProc , stk::mesh::EntityLess > new_send ;
00819   std::set< stk::mesh::Entity * ,   stk::mesh::EntityLess > new_recv ;
00820 
00821   //  Keep the closure of the remaining received ghosts.
00822   //  Working from highest-to-lowest key (rank entity type)
00823   //  results in insertion of the transitive closure.
00824   //  Insertion will not invalidate the associative container's iterator.
00825 
00826   for ( std::set< stk::mesh::Entity * , stk::mesh::EntityLess >::iterator
00827         i = new_recv.end() ; i != new_recv.begin() ; ) {
00828     --i ;
00829 
00830     const unsigned erank = (*i)->entity_rank();
00831 
00832     for ( stk::mesh::PairIterRelation
00833           irel = (*i)->relations(); ! irel.empty() ; ++irel ) {
00834       if ( irel->entity_rank() < erank &&
00835            in_receive_ghost( ghosts , * irel->entity() ) ) {
00836         new_recv.insert( irel->entity() );
00837       }
00838     }
00839   }
00840 
00841   //  Initialize the new_send from the new_recv
00842   new_comm_recv_to_send( bulk , new_recv , new_send );
00843 
00844   //------------------------------------
00845   // Add the specified entities and their closure to the send ghosting
00846 
00847   for ( std::vector< stk::mesh::EntityProc >::const_iterator
00848         i = add_send.begin() ; i != add_send.end() ; ++i ) {
00849         new_insert_transitive_closure( new_send , *i );
00850   }
00851 
00852   // Synchronize the send and receive list.
00853   // If the send list contains a not-owned entity
00854   // inform the owner and receiver to ad that entity
00855   // to their ghost send and receive lists.
00856 
00857   new_comm_sync_send_recv( bulk , new_send , new_recv );
00858 
00859   //------------------------------------
00860   // Push newly ghosted entities to the receivers and update the comm list.
00861   // Unpacking must proceed in entity-rank order so that higher ranking
00862   // entities that have relations to lower ranking entities will have
00863   // the lower ranking entities unpacked first.  The higher and lower
00864   // ranking entities may be owned by different processes,
00865   // as such unpacking must be performed in rank order.
00866 
00867   //Start of CommAll section:
00868   {
00869     stk::CommAll comm( MPI_COMM_WORLD );
00870 
00871     for ( std::set< stk::mesh::EntityProc , stk::mesh::EntityLess >::iterator
00872           j = new_send.begin(); j != new_send.end() ; ++j ) {
00873           stk::mesh::Entity & entity = * j->first ;
00874       if ( ! in_ghost( ghosts , entity , j->second ) ) {
00875         // Not already being sent , must send it.
00876         stk::CommBuffer & buf = comm.send_buffer( j->second );
00877         buf.pack<unsigned>( entity.entity_rank() );
00878         stk::mesh::pack_entity_info(  buf , entity );
00879         stk::mesh::pack_field_values( buf , entity );
00880       }
00881     }
00882 
00883     comm.allocate_buffers( size / 4 );
00884 
00885     for ( std::set< stk::mesh::EntityProc , stk::mesh::EntityLess >::iterator
00886           j = new_send.begin(); j != new_send.end() ; ++j ) {
00887           stk::mesh::Entity & entity = * j->first ;
00888       if ( ! in_ghost( ghosts , entity , j->second ) ) {
00889         // Not already being sent , must send it.
00890         stk::CommBuffer & buf = comm.send_buffer( j->second );
00891         buf.pack<unsigned>( entity.entity_rank() );
00892         stk::mesh::pack_entity_info(  buf , entity );
00893         stk::mesh::pack_field_values( buf , entity );
00894 
00895       }
00896     }
00897 
00898     comm.communicate();
00899 
00900     std::ostringstream error_msg ;
00901 
00902     for ( unsigned rank = 0 ; rank < rank_count ; ++rank ) {
00903 
00904       for ( unsigned p = 0 ; p < size ; ++p ) {
00905 
00906         stk::CommBuffer & buf = comm.recv_buffer(p);
00907 
00908         while ( buf.remaining() ) {
00909 
00910           // Only unpack if of the current entity rank.
00911           // If not the current entity rank, break the iteration
00912           // until a subsequent entity rank iteration.
00913           {
00914             unsigned this_rank = ~0u ;
00915             buf.peek<unsigned>( this_rank );
00916             if ( this_rank != rank ) break ;
00917 
00918             buf.unpack<unsigned>( this_rank );
00919           }
00920 
00921           // FIXME for Carol; the code below did not work with -np 4
00922           //STKUNIT_ASSERT_EQUAL( stk::mesh::unpack_field_values( buf , elem2 , error_msg ), false);
00923     //std::cout << "Error message for unpack_field_values = " << error_msg.str() << std::endl ;
00924 
00925         }
00926       }
00927 
00928     }
00929   }//end of CommAll section
00930 
00931   bulk.modification_end ();
00932 }
00933 
00934 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , testUninitializedMetaData )
00935 {
00936   stk::ParallelMachine pm = MPI_COMM_WORLD;
00937 
00938   stk::mesh::MetaData meta; // Construct, but do not initialize
00939   stk::mesh::BulkData bulk(meta, pm);
00940 
00941   meta.set_entity_rank_names(stk::mesh::fem::entity_rank_names(2 /*spatial-dim*/));
00942 
00943   meta.commit();
00944 
00945   bulk.modification_begin();
00946 
00947   STKUNIT_ASSERT_THROW( bulk.declare_entity(0, /*rank*/
00948                                             1, /*id*/
00949                                             stk::mesh::PartVector() ),
00950                         std::logic_error);
00951 }
00952 
00953 namespace {
00954 
00955 void new_insert_transitive_closure( std::set<stk::mesh::EntityProc,stk::mesh::EntityLess> & new_send ,
00956                                 const stk::mesh::EntityProc & entry )
00957 {
00958   // Do not insert if I can determine that this entity is already
00959   // owned or shared by the receiving processor.
00960 
00961   if ( entry.second != entry.first->owner_rank() &&
00962        ! in_shared( * entry.first , entry.second ) ) {
00963 
00964     std::pair< std::set<stk::mesh::EntityProc,stk::mesh::EntityLess>::iterator , bool >
00965       result = new_send.insert( entry );
00966 
00967     if ( result.second ) {
00968       // A new insertion, must also insert the closure
00969 
00970       const unsigned etype = entry.first->entity_rank();
00971       stk::mesh::PairIterRelation irel  = entry.first->relations();
00972 
00973       for ( ; ! irel.empty() ; ++irel ) {
00974         if ( irel->entity_rank() < etype ) {
00975           stk::mesh::EntityProc tmp( irel->entity() , entry.second );
00976           new_insert_transitive_closure( new_send , tmp );
00977         }
00978       }
00979     }
00980   }
00981 }
00982 
00983 
00984 // Synchronize the send list to the receive list.
00985 
00986 void new_comm_sync_send_recv(
00987   stk::mesh::BulkData & mesh ,
00988   std::set< stk::mesh::EntityProc , stk::mesh::EntityLess > & new_send ,
00989   std::set< stk::mesh::Entity * , stk::mesh::EntityLess > & new_recv )
00990 {
00991   const unsigned parallel_rank = mesh.parallel_rank();
00992   const unsigned parallel_size = mesh.parallel_size();
00993 
00994   stk::CommAll all( mesh.parallel() );
00995 
00996   // Communication sizing:
00997 
00998   for ( std::set< stk::mesh::EntityProc , stk::mesh::EntityLess >::iterator
00999         i = new_send.begin() ; i != new_send.end() ; ++i ) {
01000     const unsigned owner = i->first->owner_rank();
01001     all.send_buffer( i->second ).skip<stk::mesh::EntityKey>(2);
01002     if ( owner != parallel_rank ) {
01003       all.send_buffer( owner ).skip<stk::mesh::EntityKey>(2);
01004     }
01005   }
01006 
01007   all.allocate_buffers( parallel_size / 4 , false /* Not symmetric */ );
01008 
01009   // Communication packing (with message content comments):
01010   for ( std::set< stk::mesh::EntityProc , stk::mesh::EntityLess >::iterator
01011         i = new_send.begin() ; i != new_send.end() ; ) {
01012     const unsigned owner = i->first->owner_rank();
01013 
01014     // Inform receiver of ghosting, the receiver does not own
01015     // and does not share this entity.
01016     // The ghost either already exists or is a to-be-done new ghost.
01017     // This status will be resolved on the final communication pass
01018     // when new ghosts are packed and sent.
01019 
01020     const stk::mesh::EntityKey &entity_key = i->first->key();
01021     const uint64_t &proc = i->second;
01022 
01023     all.send_buffer( i->second ).pack(entity_key).pack(proc);
01024 
01025     if ( owner != parallel_rank ) {
01026       // I am not the owner of this entity.
01027       // Inform the owner of this ghosting need.
01028       all.send_buffer( owner ).pack(entity_key).pack(proc);
01029 
01030       // Erase it from my processor's ghosting responsibility:
01031       // The iterator passed to the erase method will be invalidated.
01032       std::set< stk::mesh::EntityProc , stk::mesh::EntityLess >::iterator jrem = i ; ++i ;
01033       new_send.erase( jrem );
01034     }
01035     else {
01036       ++i ;
01037     }
01038   }
01039 
01040   all.communicate();
01041 
01042   // Communication unpacking:
01043   for ( unsigned p = 0 ; p < parallel_size ; ++p ) {
01044     stk::CommBuffer & buf = all.recv_buffer(p);
01045     while ( buf.remaining() ) {
01046 
01047       stk::mesh::EntityKey entity_key;
01048       uint64_t proc(0);
01049 
01050       buf.unpack(entity_key).unpack(proc);
01051 
01052       stk::mesh::Entity * const e = mesh.get_entity( entity_key );
01053 
01054       if ( parallel_rank != proc ) {
01055         //  Receiving a ghosting need for an entity I own.
01056         //  Add it to my send list.
01057         STKUNIT_ASSERT( e != NULL );
01058         stk::mesh::EntityProc tmp( e , proc );
01059         new_send.insert( tmp );
01060       }
01061       else if ( e != NULL ) {
01062         //  I am the receiver for this ghost.
01063         //  If I already have it add it to the receive list,
01064         //  otherwise don't worry about it - I will receive
01065         //  it in the final new-ghosting communication.
01066         new_recv.insert( e );
01067       }
01068     }
01069   }
01070 }
01071 
01072 void new_comm_recv_to_send(
01073   stk::mesh::BulkData & mesh ,
01074   const std::set< stk::mesh::Entity * , stk::mesh::EntityLess > & new_recv ,
01075         std::set< stk::mesh::EntityProc , stk::mesh::EntityLess > & new_send )
01076 {
01077   const unsigned parallel_size = mesh.parallel_size();
01078 
01079   stk::CommAll all( mesh.parallel() );
01080 
01081   for ( std::set< stk::mesh::Entity * , stk::mesh::EntityLess >::const_iterator
01082         i = new_recv.begin() ; i != new_recv.end() ; ++i ) {
01083     const unsigned owner = (*i)->owner_rank();
01084     all.send_buffer( owner ).skip<stk::mesh::EntityKey>(1);
01085   }
01086 
01087   all.allocate_buffers( parallel_size / 4 , false /* Not symmetric */ );
01088 
01089   for ( std::set< stk::mesh::Entity * , stk::mesh::EntityLess >::const_iterator
01090         i = new_recv.begin() ; i != new_recv.end() ; ++i ) {
01091     const unsigned owner = (*i)->owner_rank();
01092     const stk::mesh::EntityKey key = (*i)->key();
01093     all.send_buffer( owner ).pack<stk::mesh::EntityKey>( & key , 1 );
01094   }
01095 
01096   all.communicate();
01097 
01098   for ( unsigned p = 0 ; p < parallel_size ; ++p ) {
01099     stk::CommBuffer & buf = all.recv_buffer(p);
01100     while ( buf.remaining() ) {
01101       stk::mesh::EntityKey key ;
01102       buf.unpack<stk::mesh::EntityKey>( & key , 1 );
01103       stk::mesh::EntityProc tmp( mesh.get_entity( entity_rank(key), entity_id(key) ) , p );
01104       new_send.insert( tmp );
01105     }
01106   }
01107 }
01108 
01109 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends