Sierra Toolkit Version of the Day
BulkDataGhosting.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 
00014 #include <cstring>
00015 #include <set>
00016 #include <stdexcept>
00017 #include <iostream>
00018 #include <sstream>
00019 #include <algorithm>
00020 
00021 #include <stk_util/parallel/ParallelComm.hpp>
00022 #include <stk_util/parallel/ParallelReduce.hpp>
00023 
00024 #include <stk_mesh/base/Ghosting.hpp>
00025 #include <stk_mesh/base/BulkData.hpp>
00026 #include <stk_mesh/base/MetaData.hpp>
00027 #include <stk_mesh/base/FieldData.hpp>
00028 #include <stk_mesh/base/EntityComm.hpp>
00029 #include <stk_mesh/base/Comm.hpp>
00030 
00031 using std::strcmp;
00032 
00033 namespace stk {
00034 namespace mesh {
00035 
00036 //----------------------------------------------------------------------
00037 
00038 Ghosting & BulkData::create_ghosting( const std::string & name )
00039 {
00040   static const char method[] = "stk::mesh::BulkData::create_ghosting" ;
00041 
00042   assert_ok_to_modify( method );
00043 
00044   // Verify name is the same on all processors,
00045   // if not then throw an exception on all processors.
00046   {
00047     CommBroadcast bc( parallel() , 0 );
00048 
00049     if ( bc.parallel_rank() == 0 ) {
00050       bc.send_buffer().skip<char>( name.size() + 1 );
00051     }
00052 
00053     bc.allocate_buffer();
00054 
00055     if ( bc.parallel_rank() == 0 ) {
00056       bc.send_buffer().pack<char>( name.c_str() , name.size() + 1 );
00057     }
00058 
00059     bc.communicate();
00060 
00061     const char * const bc_name =
00062       reinterpret_cast<const char *>( bc.recv_buffer().buffer() );
00063 
00064     int error = 0 != strcmp( bc_name , name.c_str() );
00065 
00066     all_reduce( parallel() , ReduceMax<1>( & error ) );
00067 
00068     if ( error ) {
00069       std::string msg("stk::mesh::BulkData::create_ghosting ERROR: Parallel name inconsistency");
00070       throw std::runtime_error( msg );
00071     }
00072   }
00073 
00074   Ghosting * const g =
00075     new Ghosting( *this , name , m_ghosting.size() , m_sync_count );
00076 
00077   m_ghosting.push_back( g );
00078 
00079   return *g ;
00080 }
00081 
00082 //----------------------------------------------------------------------
00083 //----------------------------------------------------------------------
00084 
00085 namespace {
00086 
00087 void insert_transitive_closure( std::set<EntityProc,EntityLess> & new_send ,
00088                                 const EntityProc & entry );
00089 
00090 void comm_recv_to_send(
00091   BulkData & mesh ,
00092   const std::set< Entity * , EntityLess > & new_recv ,
00093         std::set< EntityProc , EntityLess > & new_send );
00094 
00095 void comm_sync_send_recv(
00096   BulkData & mesh ,
00097   std::set< EntityProc , EntityLess > & new_send ,
00098   std::set< Entity * , EntityLess > & new_recv );
00099 
00100 } // namespace <>
00101 
00102 //----------------------------------------------------------------------
00103 //----------------------------------------------------------------------
00104 
00105 void BulkData::destroy_all_ghosting()
00106 {
00107   static const char method[] = "stk::mesh::BulkData::destroy_all_ghosting" ;
00108 
00109   assert_ok_to_modify( method );
00110 
00111   // Clear Ghosting data
00112 
00113   for ( std::vector<Ghosting*>::iterator
00114         ig = m_ghosting.begin() ; ig != m_ghosting.end() ; ++ig ) {
00115     Ghosting & gh = **ig ;
00116     gh.m_sync_count = m_sync_count ;
00117   }
00118 
00119   // Iterate backwards so as not to invalidate a closure.
00120 
00121   std::vector<Entity*>::iterator ie = m_entity_comm.end();
00122 
00123   while ( ie != m_entity_comm.begin() ) {
00124 
00125     Entity * entity = *--ie ;
00126 
00127     if ( in_receive_ghost( *entity ) ) {
00128       m_entity_repo.comm_clear( *entity );
00129       destroy_entity( entity );
00130       *ie = NULL ;
00131     }
00132     else {
00133       m_entity_repo.comm_clear_ghosting( * entity);
00134       if ( entity->comm().empty() ) {
00135         *ie = NULL ;
00136       }
00137     }
00138   }
00139 
00140   ie = std::remove( m_entity_comm.begin() ,
00141                     m_entity_comm.end() , (Entity*) NULL );
00142 
00143   m_entity_comm.erase( ie , m_entity_comm.end() );
00144 }
00145 
00146 //----------------------------------------------------------------------
00147 
00148 void BulkData::change_ghosting(
00149   Ghosting & ghosts ,
00150   const std::vector<EntityProc> & add_send ,
00151   const std::vector<Entity*> & remove_receive )
00152 {
00153   static const char method[] = "stk::mesh::BulkData::change_ghosting" ;
00154 
00155   //----------------------------------------
00156   // Verify inputs:
00157 
00158   assert_ok_to_modify( method );
00159 
00160   const bool ok_mesh  = & ghosts.mesh() == this ;
00161   const bool ok_ghost = 1 < ghosts.ordinal();
00162   bool ok_add    = true ;
00163   bool ok_remove = true ;
00164 
00165   // Verify all 'add' are locally owned.
00166 
00167   for ( std::vector<EntityProc>::const_iterator
00168         i = add_send.begin() ; ok_add && i != add_send.end() ; ++i ) {
00169     ok_add = i->first->owner_rank() == parallel_rank();
00170   }
00171 
00172   // Verify all 'remove' are members of the ghosting.
00173 
00174   for ( std::vector<Entity*>::const_iterator
00175         i = remove_receive.begin() ;
00176         ok_remove && i != remove_receive.end() ; ++i ) {
00177     ok_remove = in_receive_ghost( ghosts , **i );
00178   }
00179 
00180   int ok = ok_mesh && ok_ghost && ok_add && ok_remove ;
00181 
00182   all_reduce( parallel() , ReduceMin<1>( & ok ) );
00183 
00184   if ( 0 == ok ) {
00185     std::ostringstream msg ;
00186     msg << method << "( " << ghosts.name() << " ) ERROR" ;
00187     if ( ! ok_mesh )  { msg << " : Mesh does not own this ghosting" ; }
00188     if ( ! ok_ghost ) { msg << " : Cannot modify this ghosting" ; }
00189     if ( ! ok_add ) {
00190       msg << " : Not owned add {" ;
00191       for ( std::vector<EntityProc>::const_iterator
00192             i = add_send.begin() ; i != add_send.end() ; ++i ) {
00193         if ( i->first->owner_rank() != parallel_rank() ) {
00194           msg << " " ;
00195           print_entity_key( msg , mesh_meta_data() , i->first->key() );
00196         }
00197       }
00198       msg << " }" ;
00199     }
00200     if ( ! ok_remove ) {
00201       msg << " : Not in ghost receive {" ;
00202       for ( std::vector<Entity*>::const_iterator
00203             i = remove_receive.begin() ; i != remove_receive.end() ; ++i ) {
00204         if ( ! in_receive_ghost( ghosts , **i ) ) {
00205           msg << " " ;
00206           print_entity_key( msg , mesh_meta_data() , (*i)->key() );
00207         }
00208       }
00209     }
00210     throw std::runtime_error( msg.str() );
00211   }
00212   //----------------------------------------
00213   // Change the ghosting:
00214 
00215   internal_change_ghosting( ghosts , add_send , remove_receive );
00216 }
00217 
00218 //----------------------------------------------------------------------
00219 
00220 namespace {
00221 
00222 void require_destroy_entity( BulkData & mesh , Entity * entity ,
00223                              const char * const method )
00224 {
00225   if ( ! mesh.destroy_entity( entity ) ) {
00226     std::ostringstream msg ;
00227     msg << method << " FAILED attempt to destroy " ;
00228     print_entity_key( msg , mesh.mesh_meta_data() , entity->key() );
00229     throw std::logic_error( msg.str() );
00230   }
00231 }
00232 
00233 }
00234 
00235 void BulkData::internal_change_ghosting(
00236   Ghosting & ghosts ,
00237   const std::vector<EntityProc> & add_send ,
00238   const std::vector<Entity*> & remove_receive )
00239 {
00240   const char method[] = "stk::mesh::BulkData::internal_change_ghosting" ;
00241 
00242   const MetaData & meta = m_mesh_meta_data ;
00243   const unsigned rank_count = meta.entity_rank_count();
00244   const unsigned p_size = m_parallel_size ;
00245 
00246   //------------------------------------
00247   // Copy ghosting lists into more efficiently editted container.
00248   // The send and receive lists must be in entity rank-order.
00249 
00250   std::set< EntityProc , EntityLess > new_send ;
00251   std::set< Entity * ,   EntityLess > new_recv ;
00252 
00253   //------------------------------------
00254   // Insert the current ghost receives and then remove from that list.
00255 
00256   if ( & m_entity_comm != & remove_receive ) {
00257 
00258     for ( std::vector<Entity*>::const_iterator
00259           i = entity_comm().begin() ; i != entity_comm().end() ; ++i ) {
00260       Entity * const entity = *i ;
00261       if ( in_receive_ghost( ghosts , *entity ) ) {
00262         new_recv.insert( entity );
00263       }
00264     }
00265 
00266     // Remove any entities that are in the remove list.
00267 
00268     for ( std::vector< Entity * >::const_iterator
00269           i = remove_receive.begin() ; i != remove_receive.end() ; ++i ) {
00270       new_recv.erase( *i );
00271     }
00272 
00273     //  Keep the closure of the remaining received ghosts.
00274     //  Working from highest-to-lowest key (rank entity type)
00275     //  results in insertion of the transitive closure.
00276     //  Insertion will not invalidate the associative container's iterator.
00277 
00278     for ( std::set< Entity * , EntityLess >::iterator
00279           i = new_recv.end() ; i != new_recv.begin() ; ) {
00280       --i ;
00281 
00282       const unsigned erank = (*i)->entity_rank();
00283 
00284       for ( PairIterRelation
00285             irel = (*i)->relations(); ! irel.empty() ; ++irel ) {
00286         if ( irel->entity_rank() < erank &&
00287              in_receive_ghost( ghosts , * irel->entity() ) ) {
00288           new_recv.insert( irel->entity() );
00289         }
00290       }
00291     }
00292   }
00293 
00294   //  Initialize the new_send from the new_recv
00295   comm_recv_to_send( *this , new_recv , new_send );
00296 
00297   //------------------------------------
00298   // Add the specified entities and their closure to the send ghosting
00299 
00300   for ( std::vector< EntityProc >::const_iterator
00301         i = add_send.begin() ; i != add_send.end() ; ++i ) {
00302     insert_transitive_closure( new_send , *i );
00303   }
00304 
00305   // Synchronize the send and receive list.
00306   // If the send list contains a not-owned entity
00307   // inform the owner and receiver to ad that entity
00308   // to their ghost send and receive lists.
00309 
00310   comm_sync_send_recv( *this , new_send , new_recv );
00311 
00312   // The new_send list is now parallel complete and parallel accurate
00313   // The new_recv has those ghost entities that are to be kept.
00314   //------------------------------------
00315   // Remove the ghost entities that will not remain.
00316   // If the last reference to the receive ghost entity then delete it.
00317 
00318   bool removed = false ;
00319 
00320   for ( std::vector<Entity*>::iterator
00321         i = m_entity_comm.end() ; i != m_entity_comm.begin() ; ) {
00322 
00323     Entity * entity = *--i ;
00324 
00325     const bool is_owner = entity->owner_rank() == m_parallel_rank ;
00326     const bool remove_recv = ( ! is_owner ) &&
00327                              0 == new_recv.count( entity );
00328 
00329     if ( is_owner ) {
00330       // Is owner, potentially removing ghost-sends
00331       // Have to make a copy
00332 
00333       std::vector<EntityCommInfo> comm_ghost ;
00334 
00335       {
00336         const PairIterEntityComm ec = entity->comm( ghosts );
00337         comm_ghost.assign( ec.first , ec.second );
00338       }
00339 
00340       for ( ; ! comm_ghost.empty() ; comm_ghost.pop_back() ) {
00341         const EntityCommInfo tmp = comm_ghost.back();
00342 
00343         if ( 0 == new_send.count( EntityProc( entity , tmp.proc ) ) ) {
00344           m_entity_repo.erase_comm_info( *entity, tmp );
00345         }
00346       }
00347     }
00348     else if ( remove_recv ) {
00349       m_entity_repo.erase_ghosting( *entity, ghosts );
00350     }
00351 
00352     if ( entity->comm().empty() ) {
00353       removed = true ;
00354       *i = NULL ; // No longer communicated
00355       if ( remove_recv ) {
00356         require_destroy_entity( *this , entity , method );
00357       }
00358     }
00359   }
00360 
00361   if ( removed ) {
00362     std::vector<Entity*>::iterator i =
00363       std::remove( m_entity_comm.begin() ,
00364                    m_entity_comm.end() , (Entity*) NULL );
00365     m_entity_comm.erase( i , m_entity_comm.end() );
00366   }
00367 
00368   //------------------------------------
00369   // Push newly ghosted entities to the receivers and update the comm list.
00370   // Unpacking must proceed in entity-rank order so that higher ranking
00371   // entities that have relations to lower ranking entities will have
00372   // the lower ranking entities unpacked first.  The higher and lower
00373   // ranking entities may be owned by different processes,
00374   // as such unpacking must be performed in rank order.
00375 
00376   {
00377     const size_t entity_comm_size = m_entity_comm.size();
00378 
00379     CommAll comm( m_parallel_machine );
00380 
00381     for ( std::set< EntityProc , EntityLess >::iterator
00382           j = new_send.begin(); j != new_send.end() ; ++j ) {
00383 
00384       Entity & entity = * j->first ;
00385 
00386       if ( ! in_ghost( ghosts , entity , j->second ) ) {
00387         // Not already being sent , must send it.
00388         CommBuffer & buf = comm.send_buffer( j->second );
00389         buf.pack<unsigned>( entity.entity_rank() );
00390         pack_entity_info(  buf , entity );
00391         pack_field_values( buf , entity );
00392       }
00393     }
00394 
00395     comm.allocate_buffers( p_size / 4 );
00396 
00397     for ( std::set< EntityProc , EntityLess >::iterator
00398           j = new_send.begin(); j != new_send.end() ; ++j ) {
00399 
00400       Entity & entity = * j->first ;
00401 
00402       if ( ! in_ghost( ghosts , entity , j->second ) ) {
00403         // Not already being sent , must send it.
00404         CommBuffer & buf = comm.send_buffer( j->second );
00405         buf.pack<unsigned>( entity.entity_rank() );
00406         pack_entity_info(  buf , entity );
00407         pack_field_values( buf , entity );
00408 
00409         m_entity_repo.insert_comm_info( entity, EntityCommInfo(ghosts.ordinal(),j->second) );
00410 
00411         m_entity_comm.push_back( & entity );
00412       }
00413     }
00414 
00415     comm.communicate();
00416 
00417     std::ostringstream error_msg ;
00418     int error_count = 0 ;
00419 
00420     for ( unsigned rank = 0 ; rank < rank_count ; ++rank ) {
00421       for ( unsigned p = 0 ; p < p_size ; ++p ) {
00422         CommBuffer & buf = comm.recv_buffer(p);
00423         while ( buf.remaining() ) {
00424           // Only unpack if of the current entity rank.
00425           // If not the current entity rank, break the iteration
00426           // until a subsequent entity rank iteration.
00427           {
00428             unsigned this_rank = ~0u ;
00429             buf.peek<unsigned>( this_rank );
00430 
00431             if ( this_rank != rank ) break ;
00432 
00433             buf.unpack<unsigned>( this_rank );
00434           }
00435 
00436           PartVector parts ;
00437           std::vector<Relation> relations ;
00438           EntityKey key ;
00439           unsigned  owner = ~0u ;
00440 
00441           unpack_entity_info( buf, *this, key, owner, parts, relations );
00442 
00443           // Must not have the locally_owned_part or globally_shared_part
00444 
00445           remove( parts , meta.locally_owned_part() );
00446           remove( parts , meta.globally_shared_part() );
00447 
00448           std::pair<Entity*,bool> result =
00449             m_entity_repo.internal_create_entity( key );
00450 
00451           const bool created   = result.second ;
00452           const bool recreated = EntityLogDeleted == result.first->log_query();
00453 
00454           if ( created || recreated ) {
00455             m_entity_repo.log_created_parallel_copy( *(result.first) );
00456             m_entity_repo.set_entity_owner_rank( *(result.first), owner);
00457           }
00458 
00459           assert_entity_owner( method , * result.first , owner );
00460 
00461           internal_change_entity_parts( * result.first , parts , PartVector() );
00462 
00463           declare_relation( * result.first , relations );
00464 
00465           if ( ! unpack_field_values( buf , * result.first , error_msg ) ) {
00466             ++error_count ;
00467           }
00468 
00469           const EntityCommInfo tmp( ghosts.ordinal() , owner );
00470 
00471           if ( m_entity_repo.insert_comm_info( *(result.first), tmp ) ) {
00472             m_entity_comm.push_back( result.first );
00473           }
00474         }
00475       }
00476     }
00477 
00478     all_reduce( m_parallel_machine , ReduceSum<1>( & error_count ) );
00479 
00480     if ( error_count ) { throw std::runtime_error( error_msg.str() ); }
00481 
00482     if ( entity_comm_size < m_entity_comm.size() ) {
00483       // Added new ghosting entities to the list,
00484       // must now sort and merge.
00485 
00486       std::vector<Entity*>::iterator i = m_entity_comm.begin();
00487       i += entity_comm_size ;
00488       std::sort( i , m_entity_comm.end() , EntityLess() );
00489       std::inplace_merge( m_entity_comm.begin() , i ,
00490                           m_entity_comm.end() , EntityLess() );
00491       i = std::unique( m_entity_comm.begin() , m_entity_comm.end() );
00492       m_entity_comm.erase( i , m_entity_comm.end() );
00493     }
00494   }
00495 
00496   ghosts.m_sync_count = m_sync_count ;
00497 }
00498 
00499 //----------------------------------------------------------------------
00500 
00501 namespace {
00502 
00503 void insert_transitive_closure( std::set<EntityProc,EntityLess> & new_send ,
00504                                 const EntityProc & entry )
00505 {
00506   // Do not insert if I can determine that this entity is already
00507   // owned or shared by the receiving processor.
00508 
00509   if ( entry.second != entry.first->owner_rank() &&
00510        ! in_shared( * entry.first , entry.second ) ) {
00511 
00512     std::pair< std::set<EntityProc,EntityLess>::iterator , bool >
00513       result = new_send.insert( entry );
00514 
00515     if ( result.second ) {
00516       // A new insertion, must also insert the closure
00517 
00518       const unsigned etype = entry.first->entity_rank();
00519       PairIterRelation irel  = entry.first->relations();
00520 
00521       for ( ; ! irel.empty() ; ++irel ) {
00522         if ( irel->entity_rank() < etype ) {
00523           EntityProc tmp( irel->entity() , entry.second );
00524           insert_transitive_closure( new_send , tmp );
00525         }
00526       }
00527     }
00528   }
00529 }
00530 
00531 // Fill a new send list from the receive list.
00532 
00533 void comm_recv_to_send(
00534   BulkData & mesh ,
00535   const std::set< Entity * , EntityLess > & new_recv ,
00536         std::set< EntityProc , EntityLess > & new_send )
00537 {
00538   static const char method[] = "stk::mesh::BulkData::change_ghosting" ;
00539 
00540   const unsigned parallel_size = mesh.parallel_size();
00541 
00542   CommAll all( mesh.parallel() );
00543 
00544   for ( std::set< Entity * , EntityLess >::const_iterator
00545         i = new_recv.begin() ; i != new_recv.end() ; ++i ) {
00546     const unsigned owner = (*i)->owner_rank();
00547     all.send_buffer( owner ).skip<EntityKey>(1);
00548   }
00549 
00550   all.allocate_buffers( parallel_size / 4 , false /* Not symmetric */ );
00551 
00552   for ( std::set< Entity * , EntityLess >::const_iterator
00553         i = new_recv.begin() ; i != new_recv.end() ; ++i ) {
00554     const unsigned owner = (*i)->owner_rank();
00555     const EntityKey key = (*i)->key();
00556     all.send_buffer( owner ).pack<EntityKey>( & key , 1 );
00557   }
00558 
00559   all.communicate();
00560 
00561   for ( unsigned p = 0 ; p < parallel_size ; ++p ) {
00562     CommBuffer & buf = all.recv_buffer(p);
00563     while ( buf.remaining() ) {
00564       EntityKey key ;
00565       buf.unpack<EntityKey>( & key , 1 );
00566       EntityProc tmp( mesh.get_entity( entity_rank(key), entity_id(key) , method ) , p );
00567       new_send.insert( tmp );
00568     }
00569   }
00570 }
00571 
00572 // Synchronize the send list to the receive list.
00573 
00574 void comm_sync_send_recv(
00575   BulkData & mesh ,
00576   std::set< EntityProc , EntityLess > & new_send ,
00577   std::set< Entity * , EntityLess > & new_recv )
00578 {
00579   static const char method[] = "stk::mesh::BulkData::change_ghosting" ;
00580   const unsigned parallel_rank = mesh.parallel_rank();
00581   const unsigned parallel_size = mesh.parallel_size();
00582 
00583   CommAll all( mesh.parallel() );
00584 
00585   // Communication sizing:
00586 
00587   for ( std::set< EntityProc , EntityLess >::iterator
00588         i = new_send.begin() ; i != new_send.end() ; ++i ) {
00589     const unsigned owner = i->first->owner_rank();
00590     all.send_buffer( i->second ).skip<EntityKey>(2);
00591     if ( owner != parallel_rank ) {
00592       all.send_buffer( owner ).skip<EntityKey>(2);
00593     }
00594   }
00595 
00596   all.allocate_buffers( parallel_size / 4 , false /* Not symmetric */ );
00597 
00598   // Communication packing (with message content comments):
00599   for ( std::set< EntityProc , EntityLess >::iterator
00600         i = new_send.begin() ; i != new_send.end() ; ) {
00601     const unsigned owner = i->first->owner_rank();
00602 
00603     // Inform receiver of ghosting, the receiver does not own
00604     // and does not share this entity.
00605     // The ghost either already exists or is a to-be-done new ghost.
00606     // This status will be resolved on the final communication pass
00607     // when new ghosts are packed and sent.
00608 
00609     const EntityKey &entity_key = i->first->key();
00610     const uint64_t &proc = i->second;
00611 
00612     all.send_buffer( i->second ).pack(entity_key).pack(proc);
00613 
00614     if ( owner != parallel_rank ) {
00615       // I am not the owner of this entity.
00616       // Inform the owner of this ghosting need.
00617       all.send_buffer( owner ).pack(entity_key).pack(proc);
00618 
00619       // Erase it from my processor's ghosting responsibility:
00620       // The iterator passed to the erase method will be invalidated.
00621       std::set< EntityProc , EntityLess >::iterator jrem = i ; ++i ;
00622       new_send.erase( jrem );
00623     }
00624     else {
00625       ++i ;
00626     }
00627   }
00628 
00629   all.communicate();
00630 
00631   // Communication unpacking:
00632   for ( unsigned p = 0 ; p < parallel_size ; ++p ) {
00633     CommBuffer & buf = all.recv_buffer(p);
00634     while ( buf.remaining() ) {
00635 
00636       EntityKey entity_key;
00637       uint64_t proc(0);
00638 
00639       buf.unpack(entity_key).unpack(proc);
00640 
00641       Entity * const e = mesh.get_entity( entity_key );
00642 
00643       if ( parallel_rank != proc ) {
00644         //  Receiving a ghosting need for an entity I own.
00645         //  Add it to my send list.
00646         if ( e == NULL ) {
00647           throw std::logic_error( std::string(method) );
00648         }
00649         EntityProc tmp( e , proc );
00650         new_send.insert( tmp );
00651       }
00652       else if ( e != NULL ) {
00653         //  I am the receiver for this ghost.
00654         //  If I already have it add it to the receive list,
00655         //  otherwise don't worry about it - I will receive
00656         //  it in the final new-ghosting communication.
00657         new_recv.insert( e );
00658       }
00659     }
00660   }
00661 }
00662 
00663 } // namespace <>
00664 
00665 //----------------------------------------------------------------------
00666 //----------------------------------------------------------------------
00667 
00668 void BulkData::internal_regenerate_shared_aura()
00669 {
00670   static const char method[] =
00671     "stk::mesh::BulkData::internal_regenerate_shared_aura" ;
00672 
00673   assert_ok_to_modify( method );
00674 
00675   std::vector<EntityProc> send ;
00676 
00677   for ( std::vector<Entity*>::const_iterator
00678         i = entity_comm().begin() ; i != entity_comm().end() ; ++i ) {
00679 
00680     Entity & entity = **i ;
00681 
00682     const unsigned erank = entity.entity_rank();
00683 
00684     const PairIterEntityComm sharing = entity.sharing();
00685 
00686     for ( size_t j = 0 ; j < sharing.size() ; ++j ) {
00687 
00688       const unsigned p = sharing[j].proc ;
00689 
00690       for ( PairIterRelation
00691             rel = entity.relations() ; ! rel.empty() ; ++rel ) {
00692 
00693         Entity * const rel_entity = rel->entity();
00694 
00695         // Higher rank and I own it, ghost to the sharing processor
00696         if ( erank < rel_entity->entity_rank() &&
00697                      rel_entity->owner_rank() == m_parallel_rank &&
00698              ! in_shared( *rel_entity , p ) ) {
00699 
00700           EntityProc entry( rel_entity , p );
00701           send.push_back( entry );
00702         }
00703       }
00704     }
00705   }
00706 
00707   // Add new aura, remove all of the old aura.
00708   // The change_ghosting figures out what to actually delete and add.
00709 
00710   internal_change_ghosting( shared_aura() , send , m_entity_comm );
00711 }
00712 
00713 //----------------------------------------------------------------------
00714 //----------------------------------------------------------------------
00715 
00716 } // namespace mesh
00717 } // namespace stk
00718 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends