|
Sierra Toolkit Version of the Day
|
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