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