Sierra Toolkit Version of the Day
UnitTestBulkData.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 <sstream>
00011 #include <stdexcept>
00012 
00013 #include <stk_util/unit_test_support/stk_utest_macros.hpp>
00014 
00015 #include <stk_util/parallel/Parallel.hpp>
00016 #include <stk_mesh/base/BulkData.hpp>
00017 #include <stk_mesh/base/GetEntities.hpp>
00018 #include <stk_mesh/base/EntityComm.hpp>
00019 #include <stk_mesh/base/Comm.hpp>
00020 #include <stk_mesh/fem/TopologicalMetaData.hpp>
00021 
00022 #include <unit_tests/UnitTestBulkData.hpp>
00023 #include <unit_tests/UnitTestRingMeshFixture.hpp>
00024 
00025 STKUNIT_UNIT_TEST(UnitTestingOfBulkData, testUnit)
00026 {
00027   MPI_Barrier( MPI_COMM_WORLD );
00028   stk::mesh::UnitTestBulkData::testBulkData( MPI_COMM_WORLD );
00029   stk::mesh::UnitTestBulkData::testChangeOwner_nodes( MPI_COMM_WORLD );
00030   stk::mesh::UnitTestBulkData::testChangeOwner_loop( MPI_COMM_WORLD );
00031   stk::mesh::UnitTestBulkData::testChangeOwner_box( MPI_COMM_WORLD );
00032   stk::mesh::UnitTestBulkData::testCreateMore( MPI_COMM_WORLD );
00033   stk::mesh::UnitTestBulkData::testChangeParts( MPI_COMM_WORLD );
00034   stk::mesh::UnitTestBulkData::testChangeParts_loop( MPI_COMM_WORLD );
00035   stk::mesh::UnitTestBulkData::testDestroy_nodes( MPI_COMM_WORLD );
00036   stk::mesh::UnitTestBulkData::testDestroy_loop( MPI_COMM_WORLD );
00037   stk::mesh::UnitTestBulkData::testModifyPropagation( MPI_COMM_WORLD );
00038 }
00039 
00040 //----------------------------------------------------------------------
00041 //----------------------------------------------------------------------
00042 
00043 
00044 
00045 namespace stk {
00046 namespace mesh {
00047 
00048 bool UnitTestBulkData::modification_end( BulkData & mesh , bool aura )
00049 { return mesh.internal_modification_end( aura ); }
00050 
00051 // Unit test the Part functionality in isolation:
00052 
00053 void UnitTestBulkData::testBulkData( ParallelMachine pm )
00054 {
00055   static const char method[] = "stk::mesh::UnitTestBulkData" ;
00056 
00057   std::cout << std::endl ;
00058 
00059   std::vector<std::string> entity_names(10);
00060   for ( size_t i = 0 ; i < 10 ; ++i ) {
00061     std::ostringstream name ;
00062     name << "EntityRank" << i ;
00063     entity_names[i] = name.str();
00064   }
00065 
00066   MetaData meta( entity_names );
00067 
00068   meta.commit();
00069 
00070   BulkData bulk( meta , pm , 100 );
00071 
00072   for ( size_t i = 0 ; i < 4 ; ++i ) {
00073     STKUNIT_ASSERT( bulk.modification_begin() );
00074     STKUNIT_ASSERT_EQUAL( i , bulk.synchronized_count() );
00075     STKUNIT_ASSERT( bulk.modification_end() );
00076   }
00077 
00078   std::vector<Part*> no_parts ;
00079 
00080   Entity * e[10] ;
00081 
00082   const unsigned id = bulk.parallel_rank() + 1 ;
00083 
00084   STKUNIT_ASSERT( bulk.modification_begin() );
00085   for ( size_t i = 0 ; i < 10 ; ++i ) {
00086     e[i] = & bulk.declare_entity(  i , id , no_parts );
00087   }
00088   STKUNIT_ASSERT( bulk.modification_end() );
00089 
00090   for ( size_t i = 0 ; i < 10 ; ++i ) {
00091     STKUNIT_ASSERT( e[i] == bulk.get_entity( i , id ) );
00092   }
00093 
00094   bool ok = false ;
00095   STKUNIT_ASSERT( bulk.modification_begin() );
00096   try {
00097     bulk.declare_entity( 11 , id , no_parts );
00098   }
00099   catch( const std::exception & x ) {
00100     std::cout << method << " correctly caught: " << x.what() << std::endl ;
00101     ok = true ;
00102   }
00103   STKUNIT_ASSERT( ok );
00104   STKUNIT_ASSERT( bulk.modification_end() );
00105 
00106   // Catch not-ok-to-modify
00107   ok = false ;
00108   try {
00109     bulk.declare_entity( 0 , id + 1 , no_parts );
00110   }
00111   catch( const std::exception & x ) {
00112     ok = true ;
00113   }
00114   STKUNIT_ASSERT( ok );
00115 }
00116 
00117 //----------------------------------------------------------------------
00118 // Testing for mesh entities without relations
00119 
00120 void UnitTestBulkData::testChangeOwner_nodes( ParallelMachine pm )
00121 {
00122   enum { nPerProc = 10 };
00123   const unsigned p_rank = parallel_machine_rank( pm );
00124   const unsigned p_size = parallel_machine_size( pm );
00125   const unsigned id_total = nPerProc * p_size ;
00126   const unsigned id_begin = nPerProc * p_rank ;
00127   const unsigned id_end   = nPerProc * ( p_rank + 1 );
00128 
00129   const int spatial_dimension = 3;
00130   MetaData meta( TopologicalMetaData::entity_rank_names(spatial_dimension) );
00131   BulkData bulk( meta , pm , 100 );
00132 
00133   const PartVector no_parts ;
00134 
00135   meta.commit();
00136   bulk.modification_begin();
00137 
00138   // Ids for all entities (all entities have type 0):
00139 
00140   std::vector<EntityId> ids( id_total );
00141 
00142   for ( unsigned i = 0 ; i < id_total ; ++i ) {
00143     ids[i] = i + 1;
00144   }
00145 
00146   // Declare just those entities in my range of ids:
00147 
00148   for ( unsigned i = id_begin ; i < id_end ; ++i ) {
00149     bulk.declare_entity( 0 , ids[i] , no_parts );
00150   }
00151 
00152   STKUNIT_ASSERT( bulk.modification_end() );
00153 
00154   // Verify that I only have entities in my range:
00155 
00156   for ( unsigned i = 0 ; i < id_total ; ++i ) {
00157     Entity * e = bulk.get_entity( 0 , ids[ i ] );
00158     if ( id_begin <= i && i < id_end ) {
00159       STKUNIT_ASSERT( NULL != e );
00160     }
00161     else {
00162       STKUNIT_ASSERT( NULL == e );
00163     }
00164   }
00165 
00166   // Test change owner no-op first:
00167 
00168   std::vector<EntityProc> change ;
00169 
00170   STKUNIT_ASSERT( bulk.modification_begin() );
00171   bulk.change_entity_owner( change );
00172   STKUNIT_ASSERT( bulk.modification_end() );
00173 
00174   for ( unsigned i = 0 ; i < id_total ; ++i ) {
00175     Entity * e = bulk.get_entity( 0 , ids[ i ] );
00176     if ( id_begin <= i && i < id_end ) {
00177       STKUNIT_ASSERT( NULL != e );
00178     }
00179     else {
00180       STKUNIT_ASSERT( NULL == e );
00181     }
00182   }
00183 
00184   // Can only test changing owner in parallel.
00185 
00186   if ( 1 < p_size ) {
00187     // Give my last two ids to the next process
00188     // Get the previous process' last two ids
00189 
00190     const unsigned p_give = ( p_rank + 1 ) % p_size ;
00191     const unsigned id_give = id_end - 2 ;
00192     const unsigned id_get  = ( id_begin + id_total - 2 ) % id_total ;
00193 
00194     STKUNIT_ASSERT( NULL != bulk.get_entity( 0 , ids[id_give] ) );
00195     STKUNIT_ASSERT( NULL != bulk.get_entity( 0 , ids[id_give+1] ) );
00196     STKUNIT_ASSERT( NULL == bulk.get_entity( 0 , ids[id_get] ) );
00197     STKUNIT_ASSERT( NULL == bulk.get_entity( 0 , ids[id_get+1] ) );
00198 
00199     change.resize(2);
00200     change[0].first = bulk.get_entity( 0 , ids[id_give] );
00201     change[0].second = p_give ;
00202     change[1].first = bulk.get_entity( 0 , ids[id_give+1] );
00203     change[1].second = p_give ;
00204 
00205     STKUNIT_ASSERT( bulk.modification_begin() );
00206     bulk.change_entity_owner( change );
00207     STKUNIT_ASSERT( bulk.modification_end() );
00208 
00209     STKUNIT_ASSERT( NULL != bulk.get_entity( 0 , ids[id_get] ) );
00210     STKUNIT_ASSERT( NULL != bulk.get_entity( 0 , ids[id_get+1] ) );
00211 
00212     // Entities given away are destroyed until the next modification cycle
00213     {
00214       Entity * const e0 = bulk.get_entity( 0 , ids[id_give] );
00215       Entity * const e1 = bulk.get_entity( 0 , ids[id_give+1] );
00216       STKUNIT_ASSERT( NULL != e0 && e0->bucket().capacity() == 0 );
00217       STKUNIT_ASSERT( NULL != e1 && e1->bucket().capacity() == 0 );
00218     }
00219 
00220     STKUNIT_ASSERT( bulk.modification_begin() );
00221     STKUNIT_ASSERT( bulk.modification_end() );
00222 
00223     STKUNIT_ASSERT( NULL == bulk.get_entity( 0 , ids[id_give] ) );
00224     STKUNIT_ASSERT( NULL == bulk.get_entity( 0 , ids[id_give+1] ) );
00225   }
00226 
00227   std::cout << std::endl
00228             << "P" << p_rank
00229             << ": UnitTestBulkData::testChangeOwner_nodes( NP = "
00230             << p_size << " ) SUCCESSFULL " << std::endl ;
00231 }
00232 
00233 //----------------------------------------------------------------------
00234 // Testing for creating existing mesh entities without relations
00235 
00236 void UnitTestBulkData::testCreateMore( ParallelMachine pm )
00237 {
00238   enum { nPerProc = 10 };
00239 
00240   const unsigned p_size = parallel_machine_size( pm );
00241   const unsigned p_rank = parallel_machine_rank( pm );
00242 
00243   if ( 1 < p_size ) {
00244 
00245     std::cout << std::endl
00246               << "P" << p_rank
00247               << ": UnitTestBulkData::testCreateMore( NP = "
00248               << p_size << " )"
00249               << std::endl ;
00250     std::cout.flush();
00251 
00252     const unsigned id_total = nPerProc * p_size ;
00253     const unsigned id_begin = nPerProc * p_rank ;
00254     const unsigned id_end   = nPerProc * ( p_rank + 1 );
00255 
00256     const int spatial_dimension = 3;
00257     MetaData meta( TopologicalMetaData::entity_rank_names(spatial_dimension) );
00258 
00259     const PartVector no_parts ;
00260 
00261     meta.commit();
00262 
00263     BulkData bulk( meta , pm , 100 );
00264 
00265     bulk.modification_begin();
00266 
00267     // Ids for all entities (all entities have type 0):
00268 
00269     std::vector<EntityId> ids( id_total );
00270 
00271     for ( unsigned i = 0 ; i < id_total ; ++i ) { ids[i] = i + 1; }
00272 
00273     // Declare just those entities in my range of ids:
00274 
00275     for ( unsigned i = id_begin ; i < id_end ; ++i ) {
00276       bulk.declare_entity( 0 , ids[i] , no_parts );
00277     }
00278 
00279     STKUNIT_ASSERT( bulk.modification_end() );
00280 
00281     // Only one process create entities with previous process' last two ids
00282 
00283     const unsigned id_get  = ( id_begin + id_total - 2 ) % id_total ;
00284 
00285     STKUNIT_ASSERT( NULL == bulk.get_entity( 0 , ids[id_get] ) );
00286     STKUNIT_ASSERT( NULL == bulk.get_entity( 0 , ids[id_get+1] ) );
00287 
00288     STKUNIT_ASSERT( bulk.modification_begin() );
00289 
00290     if ( 1 == p_rank ) {
00291       // These declarations create entities that already exist,
00292       // which will be an error.  Must create an owned entity
00293       // to use them, thus they become shared.
00294 
00295       Entity & e0 = bulk.declare_entity( 0 , ids[ id_get ] , no_parts );
00296       Entity & e1 = bulk.declare_entity( 0 , ids[ id_get + 1 ] , no_parts );
00297 
00298       Entity & eU = bulk.declare_entity( 1 , 1 , no_parts );
00299 
00300       bulk.declare_relation( eU , e0 , 0 );
00301       bulk.declare_relation( eU , e1 , 1 );
00302     }
00303 
00304     bulk.modification_end();
00305 
00306     if ( 1 == p_rank ) {
00307       Entity * e0 = bulk.get_entity( 0 , ids[id_get] );
00308       Entity * e1 = bulk.get_entity( 0 , ids[id_get+1] );
00309       STKUNIT_ASSERT( NULL != e0 );
00310       STKUNIT_ASSERT( NULL != e1 );
00311       STKUNIT_ASSERT( 0 == e0->owner_rank() );
00312       STKUNIT_ASSERT( 0 == e1->owner_rank() );
00313     }
00314 
00315     // Now test tripping the error condition
00316 
00317     bulk.modification_begin();
00318 
00319     if ( 0 == p_rank ) {
00320       bulk.declare_entity( 0 , ids[ id_get ] , no_parts );
00321       bulk.declare_entity( 0 , ids[ id_get + 1 ] , no_parts );
00322     }
00323 
00324     STKUNIT_ASSERT_THROW( bulk.modification_end() , std::runtime_error );
00325   }
00326 }
00327 
00328 //----------------------------------------------------------------------
00329 //----------------------------------------------------------------------
00330 
00331 void UnitTestBulkData::testChangeOwner_loop( ParallelMachine pm )
00332 {
00333   enum { nPerProc = 10 };
00334   const unsigned p_rank = parallel_machine_rank( pm );
00335   const unsigned p_size = parallel_machine_size( pm );
00336   const unsigned nLocalNode = nPerProc + ( 1 < p_size ? 1 : 0 );
00337   const unsigned nLocalEdge = nPerProc ;
00338 
00339   std::vector<unsigned> local_count ;
00340 
00341   //------------------------------
00342   {
00343     UnitTestRingMeshFixture ring_mesh( pm , nPerProc , false /* no edge parts */ );
00344     ring_mesh.m_meta_data.commit();
00345     ring_mesh.generate_mesh( false /* no aura */ );
00346 
00347     const Selector select_used = ring_mesh.m_meta_data.locally_owned_part() |
00348                                  ring_mesh.m_meta_data.globally_shared_part() ;
00349     const Selector select_all = ring_mesh.m_meta_data.universal_part() ;
00350 
00351     count_entities( select_used , ring_mesh.m_bulk_data , local_count );
00352     STKUNIT_ASSERT_EQUAL( local_count[0] , nLocalNode );
00353     STKUNIT_ASSERT_EQUAL( local_count[1] , nLocalEdge );
00354 
00355     count_entities( select_all , ring_mesh.m_bulk_data , local_count );
00356     STKUNIT_ASSERT_EQUAL( local_count[0] , nLocalNode );
00357     STKUNIT_ASSERT_EQUAL( local_count[1] , nLocalEdge );
00358 
00359     // Shift loop by two nodes and edges.
00360 
00361     if ( 1 < p_size ) {
00362       ring_mesh.test_shift_loop( false /* no aura */ );
00363 
00364       count_entities( select_used , ring_mesh.m_bulk_data , local_count );
00365       STKUNIT_ASSERT( local_count[0] == nLocalNode );
00366       STKUNIT_ASSERT( local_count[1] == nLocalEdge );
00367 
00368       count_entities( select_all , ring_mesh.m_bulk_data , local_count );
00369       STKUNIT_ASSERT( local_count[0] == nLocalNode );
00370       STKUNIT_ASSERT( local_count[1] == nLocalEdge );
00371     }
00372   }
00373 
00374   //------------------------------
00375   // Test shift starting with ghosting but not regenerated ghosting.
00376   {
00377     UnitTestRingMeshFixture ring_mesh( pm , nPerProc , false /* no edge parts */ );
00378     ring_mesh.m_meta_data.commit();
00379     ring_mesh.generate_mesh( true /* with aura */ );
00380 
00381     const Selector select_owned( ring_mesh.m_meta_data.locally_owned_part() );
00382     const Selector select_used = ring_mesh.m_meta_data.locally_owned_part() |
00383                                  ring_mesh.m_meta_data.globally_shared_part() ;
00384     const Selector select_all(   ring_mesh.m_meta_data.universal_part() );
00385 
00386     count_entities( select_used , ring_mesh.m_bulk_data , local_count );
00387     STKUNIT_ASSERT_EQUAL( local_count[0] , nLocalNode );
00388     STKUNIT_ASSERT_EQUAL( local_count[1] , nLocalEdge );
00389 
00390     count_entities( select_all , ring_mesh.m_bulk_data , local_count );
00391     const unsigned n_extra = 1 < p_size ? 2 : 0 ;
00392     STKUNIT_ASSERT( local_count[0] == nLocalNode + n_extra );
00393     STKUNIT_ASSERT( local_count[1] == nLocalEdge + n_extra );
00394 
00395     if ( 1 < p_size ) {
00396       ring_mesh.test_shift_loop( false /* no aura */ );
00397 
00398       count_entities( select_owned , ring_mesh.m_bulk_data , local_count );
00399       STKUNIT_ASSERT( local_count[0] == nPerProc );
00400       STKUNIT_ASSERT( local_count[1] == nPerProc );
00401 
00402       count_entities( select_used , ring_mesh.m_bulk_data , local_count );
00403       STKUNIT_ASSERT( local_count[0] == nLocalNode );
00404       STKUNIT_ASSERT( local_count[1] == nLocalEdge );
00405 
00406       // All of my ghosts were disrupted and therefore deleted:
00407       count_entities( select_all , ring_mesh.m_bulk_data , local_count );
00408       STKUNIT_ASSERT_EQUAL( nLocalEdge , local_count[1] );
00409       STKUNIT_ASSERT_EQUAL( nLocalNode , local_count[0] );
00410     }
00411   }
00412   //------------------------------
00413   // Test shift starting with ghosting and regenerating ghosting.
00414   {
00415     UnitTestRingMeshFixture ring_mesh( pm , nPerProc , false /* no edge parts */ );
00416     ring_mesh.m_meta_data.commit();
00417     ring_mesh.generate_mesh( true /* with aura */ );
00418 
00419     const Selector select_owned( ring_mesh.m_meta_data.locally_owned_part() );
00420     const Selector select_used = ring_mesh.m_meta_data.locally_owned_part() |
00421                                  ring_mesh.m_meta_data.globally_shared_part() ;
00422     const Selector select_all(   ring_mesh.m_meta_data.universal_part() );
00423 
00424     count_entities( select_used , ring_mesh.m_bulk_data , local_count );
00425     STKUNIT_ASSERT( local_count[0] == nLocalNode );
00426     STKUNIT_ASSERT( local_count[1] == nLocalEdge );
00427 
00428     count_entities( select_all , ring_mesh.m_bulk_data , local_count );
00429     const unsigned n_extra = 1 < p_size ? 2 : 0 ;
00430     STKUNIT_ASSERT( local_count[0] == nLocalNode + n_extra );
00431     STKUNIT_ASSERT( local_count[1] == nLocalEdge + n_extra );
00432 
00433     if ( 1 < p_size ) {
00434       ring_mesh.test_shift_loop( true /* with aura */ );
00435 
00436       count_entities( select_owned , ring_mesh.m_bulk_data , local_count );
00437       STKUNIT_ASSERT( local_count[0] == nPerProc );
00438       STKUNIT_ASSERT( local_count[1] == nPerProc );
00439 
00440       count_entities( select_used , ring_mesh.m_bulk_data , local_count );
00441       STKUNIT_ASSERT( local_count[0] == nLocalNode );
00442       STKUNIT_ASSERT( local_count[1] == nLocalEdge );
00443 
00444       // All of my ghosts were regenerated:
00445       count_entities( select_all , ring_mesh.m_bulk_data , local_count );
00446       STKUNIT_ASSERT( local_count[0] == nLocalNode + n_extra );
00447       STKUNIT_ASSERT( local_count[1] == nLocalEdge + n_extra );
00448     }
00449   }
00450   //------------------------------
00451   // Test bad owner change catching:
00452   if ( 1 < p_size ) {
00453     UnitTestRingMeshFixture ring_mesh( pm , nPerProc , false /* no edge parts */ );
00454     ring_mesh.m_meta_data.commit();
00455     ring_mesh.generate_mesh( true /* with aura */ );
00456 
00457     std::vector<EntityProc> change ;
00458 
00459     if ( 0 == p_rank ) {
00460       change.resize(4);
00461       // Error to change to bad owner:
00462       change[0].first = ring_mesh.m_bulk_data.get_entity( 0 , ring_mesh.m_node_ids[1] );
00463       change[0].second = p_size ;
00464       // Error to change a ghost:
00465       for ( std::vector<Entity*>::const_iterator
00466             ec =  ring_mesh.m_bulk_data.entity_comm().begin() ;
00467             ec != ring_mesh.m_bulk_data.entity_comm().end() ; ++ec ) {
00468         if ( in_receive_ghost( **ec ) ) {
00469           change[1].first = *ec ;
00470           break ;
00471         }
00472       }
00473       change[1].second = p_rank ;
00474       // Error to change to multiple owners:
00475       change[2].first = ring_mesh.m_bulk_data.get_entity( 0 , ring_mesh.m_node_ids[1] );
00476       change[2].second = ( p_rank + 1 ) % p_size ;
00477       change[3].first = change[2].first ;
00478       change[3].second = ( p_rank + 2 ) % p_size ;
00479     }
00480 
00481     STKUNIT_ASSERT( ring_mesh.m_bulk_data.modification_begin() );
00482 
00483     std::string error_msg ;
00484     bool exception_thrown = false ;
00485     try {
00486       ring_mesh.m_bulk_data.change_entity_owner( change );
00487     }
00488     catch( const std::exception & x ) {
00489       exception_thrown = true ;
00490       error_msg.assign( x.what() );
00491     }
00492     STKUNIT_ASSERT( exception_thrown );
00493     std::cout
00494       << std::endl
00495       << "  UnitTestBulkData::testChangeOwner_loop SUCCESSFULLY CAUGHT: "
00496       << error_msg << std::endl ;
00497     std::cout.flush();
00498   }
00499   //------------------------------
00500   // Test move one element with initial ghosting but not regenerated ghosting:
00501   // last processor give its shared node to P0
00502   if ( 1 < p_size ) {
00503     UnitTestRingMeshFixture ring_mesh( pm , nPerProc , false /* no edge parts */ );
00504     ring_mesh.m_meta_data.commit();
00505     ring_mesh.generate_mesh( true /* with aura */ );
00506 
00507     const Selector select_owned( ring_mesh.m_meta_data.locally_owned_part() );
00508     const Selector select_used = ring_mesh.m_meta_data.locally_owned_part() |
00509                                  ring_mesh.m_meta_data.globally_shared_part() ;
00510     const Selector select_all(   ring_mesh.m_meta_data.universal_part() );
00511 
00512     std::vector<EntityProc> change ;
00513 
00514     if ( p_rank + 1 == p_size ) {
00515       EntityProc entry ;
00516       entry.first = ring_mesh.m_bulk_data.get_entity( 0 , ring_mesh.m_node_ids[0] );
00517       entry.second = 0 ;
00518       STKUNIT_ASSERT_EQUAL( p_rank , entry.first->owner_rank() );
00519       change.push_back( entry );
00520     }
00521 
00522     STKUNIT_ASSERT( ring_mesh.m_bulk_data.modification_begin() );
00523     ring_mesh.m_bulk_data.change_entity_owner( change );
00524     STKUNIT_ASSERT( UnitTestBulkData::modification_end( ring_mesh.m_bulk_data , false ) );
00525 
00526     count_entities( select_owned , ring_mesh.m_bulk_data , local_count );
00527     const unsigned n_node = p_rank == 0          ? nPerProc + 1 : (
00528                             p_rank + 1 == p_size ? nPerProc - 1 :
00529                                                    nPerProc );
00530 
00531     STKUNIT_ASSERT_EQUAL( n_node , local_count[0] );
00532     STKUNIT_ASSERT_EQUAL( (unsigned) nPerProc , local_count[1] );
00533 
00534     count_entities( select_used , ring_mesh.m_bulk_data , local_count );
00535     STKUNIT_ASSERT_EQUAL( nLocalNode , local_count[0] );
00536     STKUNIT_ASSERT_EQUAL( nLocalEdge , local_count[1] );
00537 
00538     // Moving the node disrupted ghosting on first and last process
00539     count_entities( select_all , ring_mesh.m_bulk_data , local_count );
00540     const unsigned n_extra = p_rank + 1 == p_size || p_rank == 0 ? 1 : 2 ;
00541     STKUNIT_ASSERT_EQUAL( nLocalNode + n_extra , local_count[0] );
00542     STKUNIT_ASSERT_EQUAL( nLocalEdge + n_extra , local_count[1] );
00543   }
00544 
00545   //------------------------------
00546 
00547   std::cout << std::endl
00548             << "P" << p_rank
00549             << ": UnitTestBulkData::testChangeOwner_loop( NP = "
00550             << p_size << " ) SUCCESSFULL" << std::endl ;
00551 }
00552 
00553 //----------------------------------------------------------------------
00554 //----------------------------------------------------------------------
00555 // Testing for collection of boxes
00556 
00557 namespace {
00558 
00559 void donate_one_element( BulkData & mesh , bool aura )
00560 {
00561   const unsigned p_rank = mesh.parallel_rank();
00562 
00563   Selector select_owned( mesh.mesh_meta_data().locally_owned_part() );
00564 
00565   std::vector<unsigned> before_count ;
00566   std::vector<unsigned> after_count ;
00567 
00568   count_entities( select_owned , mesh , before_count );
00569 
00570   // Change owner of an element on a process boundary
00571   // from P0 to P1, and then recount to confirm ownership change
00572 
00573   std::vector<EntityProc> change ;
00574 
00575   // A shared node:
00576   Entity * node = NULL ;
00577   Entity * elem = NULL ;
00578 
00579   for ( std::vector<Entity*>::const_iterator
00580         i =  mesh.entity_comm().begin() ;
00581         i != mesh.entity_comm().end() ; ++i ) {
00582     if ( in_shared( **i ) && (**i).entity_rank() == BaseEntityRank ) {
00583       node = *i ;
00584       break ;
00585     }
00586   }
00587 
00588   STKUNIT_ASSERT( node != NULL );
00589 
00590   for ( PairIterRelation rel = node->relations( 3 );
00591         ! rel.empty() && elem == NULL ; ++rel ) {
00592     elem = rel->entity();
00593     if ( elem->owner_rank() != p_rank ) { elem = NULL ; }
00594   }
00595 
00596   STKUNIT_ASSERT( elem != NULL );
00597 
00598   unsigned donated_nodes = 0 ;
00599 
00600   // Only process #0 donates an element and its owned nodes:
00601   if ( 0 == p_rank ) {
00602     EntityProc entry ;
00603     entry.first = elem ;
00604     entry.second = node->sharing()[0].proc ;
00605     change.push_back( entry );
00606     for ( PairIterRelation
00607           rel = elem->relations(0) ; ! rel.empty() ; ++rel ) {
00608       if ( rel->entity()->owner_rank() == p_rank ) {
00609         entry.first = rel->entity();
00610         change.push_back( entry );
00611         ++donated_nodes ;
00612       }
00613     }
00614   }
00615 
00616   STKUNIT_ASSERT( mesh.modification_begin() );
00617   mesh.change_entity_owner( change );
00618   STKUNIT_ASSERT( UnitTestBulkData::modification_end( mesh , aura ) );
00619 
00620   count_entities( select_owned , mesh , after_count );
00621 
00622   if ( 0 == p_rank ) {
00623     STKUNIT_ASSERT_EQUAL( before_count[3] - 1 , after_count[3] );
00624     STKUNIT_ASSERT_EQUAL( before_count[0] - donated_nodes, after_count[0] );
00625   }
00626 }
00627 
00628 void donate_all_shared_nodes( BulkData & mesh , bool aura )
00629 {
00630   const unsigned p_rank = mesh.parallel_rank();
00631 
00632   const Selector select_used = mesh.mesh_meta_data().locally_owned_part() |
00633                                mesh.mesh_meta_data().globally_shared_part() ;
00634 
00635   std::vector<unsigned> before_count ;
00636   std::vector<unsigned> after_count ;
00637 
00638   count_entities( select_used , mesh , before_count );
00639 
00640   // Donate owned shared nodes to first sharing process.
00641 
00642   const std::vector<Entity*> & entity_comm = mesh.entity_comm();
00643 
00644   STKUNIT_ASSERT( ! entity_comm.empty() );
00645 
00646   std::vector<EntityProc> change ;
00647 
00648   for ( std::vector<Entity*>::const_iterator
00649         i =  entity_comm.begin() ;
00650         i != entity_comm.end() &&
00651         (**i).entity_rank() == BaseEntityRank ; ++i ) {
00652     Entity * const node = *i ;
00653     const PairIterEntityComm ec = node->sharing();
00654 
00655     if ( node->owner_rank() == p_rank && ! ec.empty() ) {
00656       change.push_back( EntityProc( node , ec->proc ) );
00657     }
00658   }
00659 
00660   STKUNIT_ASSERT( mesh.modification_begin() );
00661   mesh.change_entity_owner( change );
00662   STKUNIT_ASSERT( UnitTestBulkData::modification_end( mesh , aura ) );
00663 
00664   count_entities( select_used , mesh , after_count );
00665 
00666   STKUNIT_ASSERT( 3 <= after_count.size() );
00667   STKUNIT_ASSERT_EQUAL( before_count[0] , after_count[0] );
00668   STKUNIT_ASSERT_EQUAL( before_count[1] , after_count[1] );
00669   STKUNIT_ASSERT_EQUAL( before_count[2] , after_count[2] );
00670   STKUNIT_ASSERT_EQUAL( before_count[3] , after_count[3] );
00671 }
00672 
00673 }
00674 
00675 void UnitTestBulkData::testChangeOwner_box( ParallelMachine pm )
00676 {
00677   const int root_box[3][2] = { { 0 , 4 } , { 0 , 5 } , { 0 , 6 } };
00678   int local_box[3][2] = { { 0 , 0 } , { 0 , 0 } , { 0 , 0 } };
00679 
00680   const unsigned p_rank = parallel_machine_rank( pm );
00681   const unsigned p_size = parallel_machine_size( pm );
00682 
00683   const int spatial_dimension = 3;
00684   MetaData meta( TopologicalMetaData::entity_rank_names(spatial_dimension) );
00685 
00686   meta.commit();
00687 
00688   const Selector select_owned( meta.locally_owned_part() );
00689   const Selector select_used = meta.locally_owned_part() |
00690                                meta.globally_shared_part() ;
00691   const Selector select_all(   meta.universal_part() );
00692 
00693   //------------------------------
00694   {
00695     BulkData bulk( meta , pm , 100 );
00696     bulk.modification_begin();
00697     generate_boxes( bulk , false /* no aura */ , root_box , local_box );
00698 
00699     if ( 1 < p_size ) {
00700       donate_one_element( bulk , false /* no aura */ );
00701     }
00702   }
00703 
00704   if ( 1 < p_size ) {
00705     BulkData bulk( meta , pm , 100 );
00706     bulk.modification_begin();
00707 
00708     generate_boxes( bulk , false /* no aura */ , root_box , local_box );
00709 
00710     donate_all_shared_nodes( bulk , false /* no aura */ );
00711   }
00712   //------------------------------
00713   if ( 1 < p_size ) {
00714     BulkData bulk( meta , pm , 100 );
00715     bulk.modification_begin();
00716 
00717     generate_boxes( bulk , false /* no aura */ , root_box , local_box );
00718 
00719     donate_one_element( bulk , false /* no aura */ );
00720   }
00721   //------------------------------
00722   // Introduce ghosts:
00723   if ( 1 < p_size ) {
00724     BulkData bulk( meta , pm , 100 );
00725     bulk.modification_begin();
00726 
00727     generate_boxes( bulk , true /* aura */ , root_box , local_box );
00728 
00729     std::vector<unsigned> used_count ;
00730     std::vector<unsigned> all_count ;
00731 
00732     count_entities( select_all , bulk , all_count );
00733     count_entities( select_used , bulk , used_count );
00734 
00735     STKUNIT_ASSERT( used_count[0] < all_count[0] );
00736     STKUNIT_ASSERT( used_count[3] < all_count[3] );
00737 
00738     donate_all_shared_nodes( bulk , false /* don't regenerate aura */ );
00739 
00740     count_entities( select_all , bulk , all_count );
00741     count_entities( select_used , bulk , used_count );
00742 
00743     STKUNIT_ASSERT_EQUAL( used_count[0] , all_count[0] );
00744     STKUNIT_ASSERT_EQUAL( used_count[3] , all_count[3] );
00745   }
00746   //------------------------------
00747 
00748   std::cout << std::endl
00749             << "P" << p_rank
00750             << ": UnitTestBulkData::testChangeOwner_box( NP = "
00751             << p_size << " ) SUCCESSFULL" << std::endl ;
00752 }
00753 
00754 void UnitTestBulkData::testModifyPropagation( ParallelMachine pm )
00755 {
00756   const unsigned nPerProc = 2;
00757   const unsigned p_size = parallel_machine_size( pm );
00758 
00759   // this test only needs to be run w/ one processor
00760   if (p_size > 1) return;
00761 
00762   // Make a ring_mesh and add an extra part
00763   UnitTestRingMeshFixture ring_mesh( pm , nPerProc, false /* don't use edge parts */);
00764   TopologicalMetaData & top_data = ring_mesh.m_top_data;
00765   stk::mesh::Part& special_part =
00766     ring_mesh.m_meta_data.declare_part( "special_node_part", stk::mesh::BaseEntityRank );
00767   ring_mesh.m_meta_data.commit();
00768   ring_mesh.generate_mesh();
00769 
00770   // grab the first edge
00771   stk::mesh::EntityVector edges;
00772   stk::mesh::get_entities( ring_mesh.m_bulk_data, top_data.edge_rank, edges );
00773   stk::mesh::Entity& edge = *( edges.front() );
00774 
00775   // get one of the nodes related to this edge
00776   PairIterRelation node_relations = edge.relations( stk::mesh::BaseEntityRank );
00777   STKUNIT_ASSERT( !node_relations.empty() );
00778   stk::mesh::Entity& node = *( node_relations.front().entity());
00779   STKUNIT_ASSERT_EQUAL( node.entity_rank(), (unsigned) stk::mesh::BaseEntityRank );
00780 
00781   // make a modification to the node by changing its parts
00782   ring_mesh.m_bulk_data.modification_begin();
00783   stk::mesh::PartVector parts;
00784   parts.push_back( &special_part );
00785   ring_mesh.m_bulk_data.change_entity_parts( node, parts );
00786 
00787   // check that the node AND it's edge are marked as modified
00788   STKUNIT_ASSERT_EQUAL ( node.log_query(), stk::mesh::EntityLogModified );
00789   STKUNIT_ASSERT_EQUAL ( edge.log_query(), stk::mesh::EntityLogModified );
00790 
00791   STKUNIT_ASSERT ( ring_mesh.m_bulk_data.modification_end() );
00792 }
00793 
00794 //----------------------------------------------------------------------
00795 //----------------------------------------------------------------------
00796 
00797 } // namespace mesh
00798 } // namespace stk
00799 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends