Sierra Toolkit Version of the Day
UnitTestBulkData_ChangeParts.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 <iostream>
00011 #include <sstream>
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/Comm.hpp>
00019 #include <stk_mesh/fem/EntityRanks.hpp>
00020 
00021 #include <unit_tests/UnitTestBulkData.hpp>
00022 #include <unit_tests/UnitTestRingMeshFixture.hpp>
00023 
00024 //----------------------------------------------------------------------
00025 //----------------------------------------------------------------------
00026 
00027 namespace stk {
00028 namespace mesh {
00029 
00030 //----------------------------------------------------------------------
00031 
00032 void UnitTestBulkData::testChangeParts( ParallelMachine pm )
00033 {
00034   static const char method[] =
00035     "stk::mesh::UnitTestBulkData::testChangeParts" ;
00036 
00037   std::cout << std::endl << method << std::endl ;
00038 
00039   const unsigned p_size = parallel_machine_size( pm );
00040   const unsigned p_rank = parallel_machine_rank( pm );
00041 
00042   if ( 1 < p_size ) return ;
00043 
00044   // Single process, no sharing
00045 
00046   // Meta data with entity ranks [0..9]
00047   std::vector<std::string> entity_names(10);
00048   for ( size_t i = 0 ; i < 10 ; ++i ) {
00049     std::ostringstream name ;
00050     name << "EntityRank_" << i ;
00051     entity_names[i] = name.str();
00052   }
00053 
00054   MetaData meta( entity_names );
00055   BulkData bulk( meta , pm , 100 );
00056 
00057   Part & part_univ = meta.universal_part();
00058   Part & part_owns = meta.locally_owned_part();
00059 
00060   Part & part_A_0 = meta.declare_part( std::string("A_0") , 0 );
00061   Part & part_A_1 = meta.declare_part( std::string("A_1") , 1 );
00062   Part & part_A_2 = meta.declare_part( std::string("A_2") , 2 );
00063   Part & part_A_3 = meta.declare_part( std::string("A_3") , 3 );
00064 
00065   Part & part_B_0 = meta.declare_part( std::string("B_0") , 0 );
00066   // Part & part_B_1 = meta.declare_part( std::string("B_1") , 1 );
00067   Part & part_B_2 = meta.declare_part( std::string("B_2") , 2 );
00068   // Part & part_B_3 = meta.declare_part( std::string("B_3") , 3 );
00069 
00070   meta.commit();
00071   bulk.modification_begin();
00072 
00073   PartVector tmp(1);
00074 
00075   tmp[0] = & part_A_0 ;
00076   Entity & entity_0_1 = bulk.declare_entity(  0 , 1 , tmp );
00077 
00078   tmp[0] = & part_A_1 ;
00079   Entity & entity_1_1 = bulk.declare_entity(  1 , 1 , tmp );
00080 
00081   tmp[0] = & part_A_2 ;
00082   Entity & entity_2_1 = bulk.declare_entity(  2 , 1 , tmp );
00083 
00084   tmp[0] = & part_A_3 ;
00085   Entity & entity_3_1 = bulk.declare_entity( 3 , 1 , tmp );
00086 
00087   entity_0_1.bucket().supersets( tmp );
00088   STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
00089   STKUNIT_ASSERT( tmp[0] == & part_univ );
00090   STKUNIT_ASSERT( tmp[1] == & part_owns );
00091   STKUNIT_ASSERT( tmp[2] == & part_A_0 );
00092 
00093   entity_1_1.bucket().supersets( tmp );
00094   STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
00095   STKUNIT_ASSERT( tmp[0] == & part_univ );
00096   STKUNIT_ASSERT( tmp[1] == & part_owns );
00097   STKUNIT_ASSERT( tmp[2] == & part_A_1 );
00098 
00099   entity_2_1.bucket().supersets( tmp );
00100   STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
00101   STKUNIT_ASSERT( tmp[0] == & part_univ );
00102   STKUNIT_ASSERT( tmp[1] == & part_owns );
00103   STKUNIT_ASSERT( tmp[2] == & part_A_2 );
00104 
00105   entity_3_1.bucket().supersets( tmp );
00106   STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
00107   STKUNIT_ASSERT( tmp[0] == & part_univ );
00108   STKUNIT_ASSERT( tmp[1] == & part_owns );
00109   STKUNIT_ASSERT( tmp[2] == & part_A_3 );
00110 
00111   {
00112     tmp.resize(1);
00113     tmp[0] = & part_A_0 ;
00114     bulk.change_entity_parts( entity_0_1 , tmp );
00115     entity_0_1.bucket().supersets( tmp );
00116     STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
00117     STKUNIT_ASSERT( tmp[0] == & part_univ );
00118     STKUNIT_ASSERT( tmp[1] == & part_owns );
00119     STKUNIT_ASSERT( tmp[2] == & part_A_0 );
00120   }
00121 
00122   { // Add a new part:
00123     tmp.resize(1);
00124     tmp[0] = & part_B_0 ;
00125     bulk.change_entity_parts( entity_0_1 , tmp );
00126     entity_0_1.bucket().supersets( tmp );
00127     STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
00128     STKUNIT_ASSERT( tmp[0] == & part_univ );
00129     STKUNIT_ASSERT( tmp[1] == & part_owns );
00130     STKUNIT_ASSERT( tmp[2] == & part_A_0 );
00131     STKUNIT_ASSERT( tmp[3] == & part_B_0 );
00132   }
00133 
00134   { // Remove the part just added:
00135     tmp.resize(1);
00136     tmp[0] = & part_B_0 ;
00137     bulk.change_entity_parts( entity_0_1 , PartVector() , tmp );
00138     entity_0_1.bucket().supersets( tmp );
00139     STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
00140     STKUNIT_ASSERT( tmp[0] == & part_univ );
00141     STKUNIT_ASSERT( tmp[1] == & part_owns );
00142     STKUNIT_ASSERT( tmp[2] == & part_A_0 );
00143   }
00144 
00145   { // Relationship induced membership:
00146     bulk.declare_relation( entity_1_1 , entity_0_1 , 0 );
00147     entity_0_1.bucket().supersets( tmp );
00148     STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
00149     STKUNIT_ASSERT( tmp[0] == & part_univ );
00150     STKUNIT_ASSERT( tmp[1] == & part_owns );
00151     STKUNIT_ASSERT( tmp[2] == & part_A_0 );
00152     STKUNIT_ASSERT( tmp[3] == & part_A_1 );
00153   }
00154 
00155   { // Remove relationship induced membership:
00156     bulk.destroy_relation( entity_1_1 , entity_0_1 );
00157     entity_0_1.bucket().supersets( tmp );
00158     STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
00159     STKUNIT_ASSERT( tmp[0] == & part_univ );
00160     STKUNIT_ASSERT( tmp[1] == & part_owns );
00161     STKUNIT_ASSERT( tmp[2] == & part_A_0 );
00162   }
00163 
00164   { // Add a new part:
00165     tmp.resize(1);
00166     tmp[0] = & part_B_2 ;
00167     bulk.change_entity_parts( entity_2_1 , tmp );
00168     entity_2_1.bucket().supersets( tmp );
00169     STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
00170     STKUNIT_ASSERT( tmp[0] == & part_univ );
00171     STKUNIT_ASSERT( tmp[1] == & part_owns );
00172     STKUNIT_ASSERT( tmp[2] == & part_A_2 );
00173     STKUNIT_ASSERT( tmp[3] == & part_B_2 );
00174   }
00175 
00176   { // Relationship induced membership:
00177     bulk.declare_relation( entity_2_1 , entity_0_1 , 0 );
00178     entity_0_1.bucket().supersets( tmp );
00179     STKUNIT_ASSERT_EQUAL( size_t(5) , tmp.size() );
00180     STKUNIT_ASSERT( tmp[0] == & part_univ );
00181     STKUNIT_ASSERT( tmp[1] == & part_owns );
00182     STKUNIT_ASSERT( tmp[2] == & part_A_0 );
00183     STKUNIT_ASSERT( tmp[3] == & part_A_2 );
00184     STKUNIT_ASSERT( tmp[4] == & part_B_2 );
00185   }
00186 
00187   { // Remove relationship induced membership:
00188     bulk.destroy_relation( entity_2_1 , entity_0_1 );
00189     entity_0_1.bucket().supersets( tmp );
00190     STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
00191     STKUNIT_ASSERT( tmp[0] == & part_univ );
00192     STKUNIT_ASSERT( tmp[1] == & part_owns );
00193     STKUNIT_ASSERT( tmp[2] == & part_A_0 );
00194   }
00195 
00196   bulk.modification_end();
00197 
00198   //------------------------------
00199   // Now the parallel fun.  Existing entities should be shared
00200   // by all processes since they have the same identifiers.
00201   // They should also have the same parts.
00202 
00203   entity_0_1.bucket().supersets( tmp );
00204   if ( entity_0_1.owner_rank() == p_rank ) {
00205     STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
00206     STKUNIT_ASSERT( tmp[0] == & part_univ );
00207     STKUNIT_ASSERT( tmp[1] == & part_owns );
00208     STKUNIT_ASSERT( tmp[2] == & part_A_0 );
00209   }
00210   else {
00211     STKUNIT_ASSERT_EQUAL( size_t(2) , tmp.size() );
00212     STKUNIT_ASSERT( tmp[0] == & part_univ );
00213     STKUNIT_ASSERT( tmp[1] == & part_A_0 );
00214   }
00215 
00216   entity_2_1.bucket().supersets( tmp );
00217   if ( entity_2_1.owner_rank() == p_rank ) {
00218     STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
00219     STKUNIT_ASSERT( tmp[0] == & part_univ );
00220     STKUNIT_ASSERT( tmp[1] == & part_owns );
00221     STKUNIT_ASSERT( tmp[2] == & part_A_2 );
00222     STKUNIT_ASSERT( tmp[3] == & part_B_2 );
00223   }
00224   else {
00225     STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
00226     STKUNIT_ASSERT( tmp[0] == & part_univ );
00227     STKUNIT_ASSERT( tmp[1] == & part_A_2 );
00228     STKUNIT_ASSERT( tmp[2] == & part_B_2 );
00229   }
00230 
00231   if (bulk.parallel_size() > 1) {
00232     STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_0_1.sharing().size() );
00233     STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_1_1.sharing().size() );
00234     STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_2_1.sharing().size() );
00235     STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_3_1.sharing().size() );
00236   }
00237 
00238   bulk.modification_begin();
00239 
00240   // Add a new part on the owning process:
00241 
00242   int ok_to_modify = entity_0_1.owner_rank() == p_rank ;
00243 
00244   try {
00245     tmp.resize(1);
00246     tmp[0] = & part_B_0 ;
00247     bulk.change_entity_parts( entity_0_1 , tmp );
00248     STKUNIT_ASSERT( ok_to_modify );
00249   }
00250   catch( const std::exception & x ) {
00251     STKUNIT_ASSERT( ! ok_to_modify );
00252   }
00253 
00254   entity_0_1.bucket().supersets( tmp );
00255   if ( entity_0_1.owner_rank() == p_rank ) {
00256     STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
00257     STKUNIT_ASSERT( tmp[0] == & part_univ );
00258     STKUNIT_ASSERT( tmp[1] == & part_owns );
00259     STKUNIT_ASSERT( tmp[2] == & part_A_0 );
00260     STKUNIT_ASSERT( tmp[3] == & part_B_0 );
00261   }
00262   else {
00263     STKUNIT_ASSERT_EQUAL( size_t(2) , tmp.size() );
00264     STKUNIT_ASSERT( tmp[0] == & part_univ );
00265     STKUNIT_ASSERT( tmp[1] == & part_A_0 );
00266   }
00267 
00268   bulk.modification_end();
00269 
00270   entity_0_1.bucket().supersets( tmp );
00271   if ( entity_0_1.owner_rank() == p_rank ) {
00272     STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
00273     STKUNIT_ASSERT( tmp[0] == & part_univ );
00274     STKUNIT_ASSERT( tmp[1] == & part_owns );
00275     STKUNIT_ASSERT( tmp[2] == & part_A_0 );
00276     STKUNIT_ASSERT( tmp[3] == & part_B_0 );
00277   }
00278   else {
00279     STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
00280     STKUNIT_ASSERT( tmp[0] == & part_univ );
00281     STKUNIT_ASSERT( tmp[1] == & part_A_0 );
00282     STKUNIT_ASSERT( tmp[2] == & part_B_0 );
00283   }
00284 }
00285 
00286 //----------------------------------------------------------------------
00287 //----------------------------------------------------------------------
00288 
00289 void UnitTestBulkData::testChangeParts_loop( ParallelMachine pm )
00290 {
00291   enum { nPerProc = 10 };
00292   const unsigned p_rank = parallel_machine_rank( pm );
00293   const unsigned p_size = parallel_machine_size( pm );
00294   const unsigned nLocalNode = nPerProc + ( 1 < p_size ? 1 : 0 );
00295   const unsigned nLocalEdge = nPerProc ;
00296 
00297   UnitTestRingMeshFixture ring_mesh( pm , nPerProc , true /* generate parts */ );
00298   ring_mesh.m_meta_data.commit();
00299   ring_mesh.generate_mesh( false /* no aura */ );
00300 
00301   Part & part_owns = ring_mesh.m_meta_data.locally_owned_part();
00302   Part & part_univ = ring_mesh.m_meta_data.universal_part();
00303 
00304   Selector select_owned( ring_mesh.m_meta_data.locally_owned_part() );
00305   Selector select_used = select_owned | ring_mesh.m_meta_data.globally_shared_part();
00306   Selector select_all(   ring_mesh.m_meta_data.universal_part() );
00307 
00308   std::vector<unsigned> local_count ;
00309 
00310   for ( unsigned i = 0 ; i < nLocalEdge ; ++i ) {
00311     const unsigned n = i + nPerProc * p_rank ;
00312     Entity * const edge = ring_mesh.m_bulk_data.get_entity( 1 , ring_mesh.m_edge_ids[n] );
00313     STKUNIT_ASSERT( edge != NULL );
00314     STKUNIT_ASSERT( edge->bucket().member( part_univ ) );
00315     STKUNIT_ASSERT( edge->bucket().member( part_owns ) );
00316     STKUNIT_ASSERT( edge->bucket().member( * ring_mesh.m_edge_parts[ n % ring_mesh.m_edge_parts.size() ] ) );
00317   }
00318 
00319   for ( unsigned i = 0 ; i < nLocalNode ; ++i ) {
00320     const unsigned n = ( i + nPerProc * p_rank ) % ring_mesh.m_node_ids.size();
00321     const unsigned e0 = n ;
00322     const unsigned e1 = ( n + ring_mesh.m_edge_ids.size() - 1 ) % ring_mesh.m_edge_ids.size();
00323     const unsigned ns = ring_mesh.m_edge_parts.size();
00324     const unsigned n0 = e0 % ns ;
00325     const unsigned n1 = e1 % ns ;
00326     Part * const epart_0 = ring_mesh.m_edge_parts[ n0 < n1 ? n0 : n1 ];
00327     Part * const epart_1 = ring_mesh.m_edge_parts[ n0 < n1 ? n1 : n0 ];
00328 
00329     Entity * const node = ring_mesh.m_bulk_data.get_entity( 0 , ring_mesh.m_node_ids[n] );
00330     STKUNIT_ASSERT( node != NULL );
00331     if ( node->owner_rank() == p_rank ) {
00332       STKUNIT_ASSERT( node->bucket().member( part_univ ) );
00333       STKUNIT_ASSERT( node->bucket().member( part_owns ) );
00334       STKUNIT_ASSERT( node->bucket().member( *epart_0 ) );
00335       STKUNIT_ASSERT( node->bucket().member( *epart_1 ) );
00336     }
00337     else {
00338       STKUNIT_ASSERT( node->bucket().member( part_univ ) );
00339       STKUNIT_ASSERT( ! node->bucket().member( part_owns ) );
00340       STKUNIT_ASSERT( node->bucket().member( * epart_0 ) );
00341       STKUNIT_ASSERT( node->bucket().member( * epart_1 ) );
00342     }
00343   }
00344 
00345   ring_mesh.m_bulk_data.modification_begin();
00346 
00347   if ( 0 == p_rank ) {
00348 
00349     for ( unsigned i = 0 ; i < nLocalEdge ; ++i ) {
00350       const unsigned n = i + nPerProc * p_rank ;
00351 
00352       PartVector add(1); add[0] = & ring_mesh.m_edge_part_extra ;
00353       PartVector rem(1); rem[0] = ring_mesh.m_edge_parts[ n % ring_mesh.m_edge_parts.size() ];
00354 
00355       Entity * const edge = ring_mesh.m_bulk_data.get_entity( 1 , ring_mesh.m_edge_ids[n] );
00356       ring_mesh.m_bulk_data.change_entity_parts( *edge , add , rem );
00357       STKUNIT_ASSERT( edge->bucket().member( part_univ ) );
00358       STKUNIT_ASSERT( edge->bucket().member( part_owns ) );
00359       STKUNIT_ASSERT( edge->bucket().member(ring_mesh.m_edge_part_extra ) );
00360     }
00361   }
00362 
00363   ring_mesh.m_bulk_data.modification_end();
00364 
00365   for ( unsigned i = 0 ; i < nLocalNode ; ++i ) {
00366     const unsigned n = ( i + nPerProc * p_rank ) % ring_mesh.m_node_ids.size();
00367     const unsigned e0 = n ;
00368     const unsigned e1 = ( n + ring_mesh.m_edge_ids.size() - 1 ) % ring_mesh.m_edge_ids.size();
00369     const unsigned ns = ring_mesh.m_edge_parts.size();
00370     const unsigned n0 = e0 % ns ;
00371     const unsigned n1 = e1 % ns ;
00372     Part * ep_0 = e0 < nLocalEdge ? & ring_mesh.m_edge_part_extra : ring_mesh.m_edge_parts[n0] ;
00373     Part * ep_1 = e1 < nLocalEdge ? & ring_mesh.m_edge_part_extra : ring_mesh.m_edge_parts[n1] ;
00374 
00375     Part * epart_0 = ep_0->mesh_meta_data_ordinal() < ep_1->mesh_meta_data_ordinal() ? ep_0 : ep_1 ;
00376     Part * epart_1 = ep_0->mesh_meta_data_ordinal() < ep_1->mesh_meta_data_ordinal() ? ep_1 : ep_0 ;
00377 
00378     Entity * const node = ring_mesh.m_bulk_data.get_entity( 0 , ring_mesh.m_node_ids[n] );
00379     STKUNIT_ASSERT( node != NULL );
00380     if ( node->owner_rank() == p_rank ) {
00381       STKUNIT_ASSERT( node->bucket().member( part_owns ) );
00382     }
00383     else {
00384       STKUNIT_ASSERT( ! node->bucket().member( part_owns ) );
00385     }
00386 
00387     STKUNIT_ASSERT( node->bucket().member( part_univ ) );
00388     STKUNIT_ASSERT( node->bucket().member( *epart_0 ) );
00389     STKUNIT_ASSERT( node->bucket().member( *epart_1 ) );
00390   }
00391 }
00392 
00393 } // namespace mesh
00394 } // namespace stk
00395 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends