|
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 00013 //---------------------------------------------------------------------- 00014 00015 #include <stdexcept> 00016 #include <iostream> 00017 #include <sstream> 00018 #include <set> 00019 #include <vector> 00020 #include <algorithm> 00021 00022 #include <stk_util/parallel/ParallelComm.hpp> 00023 #include <stk_util/parallel/ParallelReduce.hpp> 00024 00025 #include <stk_mesh/base/BulkData.hpp> 00026 #include <stk_mesh/base/MetaData.hpp> 00027 #include <stk_mesh/base/Entity.hpp> 00028 #include <stk_mesh/base/EntityComm.hpp> 00029 #include <stk_mesh/base/Bucket.hpp> 00030 00031 //---------------------------------------------------------------------- 00032 00033 namespace stk { 00034 namespace mesh { 00035 00036 bool comm_mesh_verify_parallel_consistency( 00037 BulkData & M , std::ostream & error_log ); 00038 00039 //---------------------------------------------------------------------- 00040 00041 unsigned BulkData::determine_new_owner( Entity & entity ) const 00042 { 00043 // The local process is a candidate only if the entity is not destroyed. 00044 unsigned new_owner = 00045 EntityLogDeleted == entity.log_query() ? ~0u : m_parallel_rank ; 00046 00047 for ( PairIterEntityComm 00048 share = entity.sharing(); ! share.empty() ; ++share ) { 00049 if ( share->proc < m_parallel_size && 00050 ( new_owner < share->proc || m_parallel_size <= new_owner ) ) { 00051 new_owner = share->proc ; 00052 } 00053 } 00054 00055 return new_owner ; 00056 } 00057 00058 //---------------------------------------------------------------------- 00059 00060 namespace { 00061 00062 // A method for quickly finding an entity 00063 Entity* find_entity(const EntityVector& entities, const EntityKey& key, 00064 bool expect_success = false) 00065 { 00066 EntityVector::const_iterator itr = 00067 std::lower_bound(entities.begin(), 00068 entities.end(), 00069 key, 00070 EntityLess()); 00071 if (itr == entities.end() || (*itr)->key() != key) { 00072 if (expect_success) { 00073 std::ostringstream err; 00074 err << "Expected to be able to find entity of type: " << key.type() 00075 << " and rank: " << key.rank(); 00076 throw std::logic_error(err.str()); 00077 } 00078 else { 00079 return NULL; 00080 } 00081 } 00082 return *itr; 00083 } 00084 00085 struct EntityProcState { 00086 EntityProc entity_proc; 00087 EntityModificationLog state; 00088 00089 bool operator<(const EntityProcState& rhs) const 00090 { 00091 EntityLess el; 00092 return el(entity_proc, rhs.entity_proc); 00093 } 00094 }; 00095 00096 bool pack_entity_modification( const BulkData & mesh , 00097 const bool pack_shared , 00098 CommAll & comm ) 00099 { 00100 bool flag = false ; 00101 00102 const std::vector<Entity*> & entity_comm = mesh.entity_comm(); 00103 00104 for ( std::vector<Entity*>::const_iterator 00105 i = entity_comm.begin() ; i != entity_comm.end() ; ++i ) { 00106 00107 Entity & entity = **i ; 00108 00109 if ( entity.log_query() == EntityLogModified || 00110 entity.log_query() == EntityLogDeleted ) { 00111 00112 for ( PairIterEntityComm ec = entity.comm(); ! ec.empty() ; ++ec ) { 00113 const bool shared = 0 == ec->ghost_id ; 00114 if ( pack_shared == shared ) { 00115 comm.send_buffer( ec->proc ) 00116 .pack<EntityKey>( entity.key() ) 00117 .pack<EntityModificationLog>( entity.log_query() ); 00118 00119 flag = true ; 00120 } 00121 } 00122 } 00123 } 00124 00125 return flag ; 00126 } 00127 00128 void communicate_entity_modification( const BulkData & mesh , 00129 const bool shared , 00130 std::vector<EntityProcState > & data ) 00131 { 00132 CommAll comm( mesh.parallel() ); 00133 00134 // Sizing send buffers: 00135 const bool local_mod = pack_entity_modification( mesh , shared , comm ); 00136 00137 // Allocation of send and receive buffers: 00138 const bool global_mod = 00139 comm.allocate_buffers( comm.parallel_size() / 4 , false , local_mod ); 00140 00141 if ( global_mod ) { 00142 const std::vector<Entity*> & entity_comm = mesh.entity_comm(); 00143 00144 // Packing send buffers: 00145 pack_entity_modification( mesh , shared , comm ); 00146 00147 comm.communicate(); 00148 00149 for ( unsigned p = 0 ; p < comm.parallel_size() ; ++p ) { 00150 CommBuffer & buf = comm.recv_buffer( p ); 00151 EntityKey key ; 00152 EntityProcState tmp ; 00153 00154 while ( buf.remaining() ) { 00155 00156 buf.unpack<EntityKey>( key ) 00157 .unpack<EntityModificationLog>( tmp.state ); 00158 00159 // search through entity_comm, should only receive info on entities 00160 // that are communicated. 00161 tmp.entity_proc.first = find_entity(entity_comm, key, true); 00162 tmp.entity_proc.second = p ; 00163 00164 data.push_back( tmp ); 00165 } 00166 } 00167 } 00168 00169 std::sort( data.begin() , data.end() ); 00170 } 00171 00172 } 00173 00174 //---------------------------------------------------------------------- 00175 //---------------------------------------------------------------------- 00176 00177 void BulkData::internal_update_distributed_index( 00178 std::vector<Entity*> & shared_new ) 00179 { 00180 std::vector< parallel::DistributedIndex::KeyType > 00181 new_entities_keys , del_entities_keys ; 00182 00183 std::vector< parallel::DistributedIndex::KeyProc > 00184 new_entities_keyprocs ; 00185 00186 for ( impl::EntityRepository::iterator 00187 i = m_entity_repo.begin() ; i != m_entity_repo.end() ; ++i ) { 00188 00189 Entity & entity = * i->second ; 00190 00191 if ( EntityLogDeleted == entity.log_query() ) { 00192 // Has been destroyed 00193 del_entities_keys.push_back( entity.key().raw_key() ); 00194 } 00195 else if ( EntityLogNoChange != entity.log_query() && 00196 in_owned_closure( entity , m_parallel_rank ) ) { 00197 // Has been changed and is in owned closure, may be shared 00198 new_entities_keys.push_back( entity.key().raw_key() ); 00199 } 00200 } 00201 00202 //------------------------------ 00203 // Update distributed index. 00204 00205 m_entities_index.update_keys( new_entities_keys , del_entities_keys ); 00206 00207 //------------------------------ 00208 // Inform creating processes: 00209 00210 m_entities_index.query_to_usage( new_entities_keys , new_entities_keyprocs ); 00211 00212 { 00213 Entity * entity = NULL ; 00214 00215 for ( std::vector< parallel::DistributedIndex::KeyProc >::iterator 00216 i = new_entities_keyprocs.begin() ; 00217 i != new_entities_keyprocs.end() ; ++i ) { 00218 00219 EntityKey key( & i->first ); 00220 00221 if ( (int) m_parallel_rank != i->second ) { 00222 // Another process also created or updated this entity. 00223 00224 if ( entity == NULL || entity->key() != key ) { 00225 // Have not looked this entity up by key 00226 entity = get_entity( key ); 00227 00228 shared_new.push_back( entity ); 00229 } 00230 00231 // Add the other_process to the entity's sharing info. 00232 m_entity_repo.insert_comm_info( *entity, EntityCommInfo( 0 , i->second ) ); 00233 } 00234 } 00235 } 00236 } 00237 00238 //---------------------------------------------------------------------- 00239 //---------------------------------------------------------------------- 00240 00241 namespace { 00242 00243 // Enforce that shared entities must be in the owned closure: 00244 00245 void destroy_dependent_ghosts( BulkData & mesh , Entity * entity ) 00246 { 00247 static const char method[] = 00248 "stk::mesh::BulkData::modification_end() { destroy_dependent_ghosts() }" ; 00249 00250 for ( ; ; ) { 00251 PairIterRelation rel = entity->relations(); 00252 00253 if ( rel.empty() ) { break ; } 00254 00255 Entity * e = rel.back().entity(); 00256 00257 if ( e->entity_rank() < entity->entity_rank() ) { break ; } 00258 00259 if ( in_owned_closure( *e , mesh.parallel_rank() ) ) { 00260 throw std::logic_error( std::string(method) ); 00261 } 00262 00263 destroy_dependent_ghosts( mesh , e ); 00264 } 00265 00266 mesh.destroy_entity( entity ); 00267 } 00268 00269 // Entities with sharing information that are not in the owned closure 00270 // have been modified such that they are no longer shared. 00271 // These may no longer be needed or may become ghost entities. 00272 // There is not enough information so assume they are to be deleted 00273 // and let these entities be re-ghosted if they are needed. 00274 00275 // Open question: Should an owned and shared entity that does not 00276 // have an upward relation to an owned entity be destroyed so that 00277 // ownership transfers to another process? 00278 00279 void resolve_shared_removed_from_owned_closure( BulkData & mesh ) 00280 { 00281 for ( std::vector<Entity*>::const_iterator 00282 i = mesh.entity_comm().end() ; 00283 i != mesh.entity_comm().begin() ; ) { 00284 00285 Entity * entity = *--i ; 00286 00287 if ( ! entity->sharing().empty() && 00288 ! in_owned_closure( *entity , mesh.parallel_rank() ) ) { 00289 00290 destroy_dependent_ghosts( mesh , entity ); 00291 } 00292 } 00293 } 00294 00295 } 00296 00297 // Resolve modifications for shared entities: 00298 // If not locally destroyed and remotely modified 00299 // then set to locally modified. 00300 // If remotely destroyed then determine the new owner. 00301 // 00302 // Post condition: 00303 // Shared entities are in-sync with respect to modification state. 00304 // Shared communication lists are updated to reflect all deletions. 00305 // Ownership has been re-assigned as necessary for deletion 00306 // of shared entities. 00307 00308 void BulkData::internal_resolve_shared_modify_delete() 00309 { 00310 resolve_shared_removed_from_owned_closure( *this ); 00311 00312 std::vector< EntityProcState > remote_mod ; 00313 00314 // Communicate entity modification state for shared entities 00315 // the resulting vector is sorted by entity and process. 00316 { 00317 const bool communicate_shared = true ; 00318 communicate_entity_modification( *this , communicate_shared , remote_mod ); 00319 } 00320 00321 // We iterate backwards over remote_mod to ensure that we hit the 00322 // higher-ranking entities first. 00323 for ( std::vector<EntityProcState>::iterator 00324 i = remote_mod.end(); i != remote_mod.begin() ; ) { 00325 00326 --i ; 00327 00328 Entity * const entity = i->entity_proc.first ; 00329 const unsigned remote_proc = i->entity_proc.second ; 00330 const bool remotely_destroyed = EntityLogDeleted == i->state ; 00331 const bool locally_destroyed = EntityLogDeleted == entity->log_query(); 00332 00333 // When a shared entity is remotely modified or destroyed 00334 // then the local copy is also modified. This modification 00335 // status is applied to all related higher ranking entities. 00336 00337 if ( ! locally_destroyed ) { 00338 m_entity_repo.modify_and_propagate( *entity ); 00339 } 00340 00341 // A shared entity is being deleted on the remote process. 00342 // Remove it from the sharing communication list. 00343 // Ownership changes are processed later based upon 00344 // the final modification state and sharing communication. 00345 00346 if ( remotely_destroyed ) { 00347 m_entity_repo.erase_comm_info( *entity, EntityCommInfo(0,remote_proc) ); 00348 } 00349 00350 // If this is the last information update on this entity 00351 // then time to resolve ownership. 00352 00353 const bool last_update_of_this_entity = 00354 (i == remote_mod.begin() || entity != (i-1)->entity_proc.first); 00355 00356 if ( last_update_of_this_entity ) { 00357 00358 PairIterEntityComm new_sharing = entity->sharing(); 00359 const bool delete_everywhere = locally_destroyed && new_sharing.empty(); 00360 00361 if ( ! delete_everywhere ) { 00362 00363 const bool old_local_owner = m_parallel_rank == entity->owner_rank(); 00364 00365 // Giving away ownership to another process in the sharing list: 00366 const bool give_ownership = locally_destroyed && old_local_owner ; 00367 00368 // The remote owner has been destroyed, choose a new owner 00369 const bool remote_owner_destroyed = 00370 ! old_local_owner && ! in_shared( *entity , entity->owner_rank() ); 00371 00372 if ( give_ownership || remote_owner_destroyed ) { 00373 00374 const unsigned new_owner = determine_new_owner( *entity ); 00375 00376 m_entity_repo.set_entity_owner_rank( *entity, new_owner ); 00377 m_entity_repo.set_entity_sync_count( *entity, m_sync_count ); 00378 } 00379 00380 if ( ! locally_destroyed ) { 00381 00382 PartVector add_part , remove_part ; 00383 00384 if ( new_sharing.empty() ) { 00385 // Is no longer shared, remove the shared part. 00386 remove_part.push_back(& m_mesh_meta_data.globally_shared_part()); 00387 } 00388 00389 const bool new_local_owner = m_parallel_rank == entity->owner_rank(); 00390 00391 const bool local_claimed_ownership = 00392 ( ! old_local_owner && new_local_owner ); 00393 00394 if ( local_claimed_ownership ) { 00395 // Changing remotely owned to locally owned 00396 add_part.push_back( & m_mesh_meta_data.locally_owned_part() ); 00397 } 00398 00399 if ( ! add_part.empty() || ! remove_part.empty() ) { 00400 internal_change_entity_parts( *entity , add_part , remove_part ); 00401 } 00402 } // if ( ! locally_destroyed ) 00403 } // if ( ! delete_everywhere ) 00404 } // last touch of this shared entity 00405 } 00406 00407 // Erase all sharing communication lists for Destroyed entities: 00408 for ( std::vector<Entity*>::const_iterator 00409 i = entity_comm().end() ; i != entity_comm().begin() ; ) { 00410 Entity * entity = *--i ; 00411 00412 if ( EntityLogDeleted == entity->log_query() ) { 00413 // m_ghosting[0] is the SHARED communication 00414 m_entity_repo.erase_ghosting( *entity , *m_ghosting[0] ); 00415 } 00416 } 00417 } 00418 00419 //---------------------------------------------------------------------- 00420 // Resolve modifications for ghosted entities: 00421 // If a ghosted entity is modified or destroyed on the owning 00422 // process then the ghosted entity must be destroyed. 00423 // 00424 // Post condition: 00425 // Ghosted entities of modified or deleted entities are destroyed. 00426 // Ghosted communication lists are cleared to reflect all deletions. 00427 00428 void BulkData::internal_resolve_ghosted_modify_delete() 00429 { 00430 // Resolve modifications for ghosted entities: 00431 00432 std::vector<EntityProcState > remote_mod ; 00433 00434 // Communicate entity modification state for ghost entities 00435 { 00436 const bool communicate_shared = false ; 00437 communicate_entity_modification( *this , communicate_shared , remote_mod ); 00438 } 00439 00440 const size_t ghosting_count = m_ghosting.size(); 00441 00442 std::vector< int > ghosting_change_flags( ghosting_count , 0 ); 00443 00444 // We iterate backwards over remote_mod to ensure that we hit the 00445 // higher-ranking entities first. This is important because higher-ranking 00446 // entities like element must be deleted before the nodes they have are 00447 // deleted. 00448 for ( std::vector<EntityProcState>::iterator 00449 i = remote_mod.end(); i != remote_mod.begin() ; ) { 00450 00451 --i ; 00452 00453 Entity * entity = i->entity_proc.first ; 00454 const unsigned remote_proc = i->entity_proc.second ; 00455 const bool local_owner = entity->owner_rank() == m_parallel_rank ; 00456 const bool remotely_destroyed = EntityLogDeleted == i->state ; 00457 const bool locally_destroyed = EntityLogDeleted == entity->log_query(); 00458 00459 if ( local_owner ) { // Sending to 'remote_proc' for ghosting 00460 00461 if ( remotely_destroyed ) { 00462 00463 // remove from ghost-send list 00464 00465 for ( size_t j = ghosting_count ; j-- ; ) { 00466 if ( m_entity_repo.erase_comm_info( *entity, EntityCommInfo( j , remote_proc ) ) ) { 00467 ghosting_change_flags[ j ] = true ; 00468 } 00469 } 00470 } 00471 00472 // Remotely modified ghosts are ignored 00473 00474 } 00475 else { // Receiving from 'remote_proc' for ghosting 00476 00477 // Owner modified or destroyed, must locally destroy. 00478 00479 for ( PairIterEntityComm ec = entity->comm() ; ! ec.empty() ; ++ec ) { 00480 ghosting_change_flags[ ec->ghost_id ] = true ; 00481 } 00482 00483 // This is a receive ghost so the only communication information 00484 // is the ghosting information, can clear it all out. 00485 m_entity_repo.comm_clear( *entity ); 00486 00487 if ( ! locally_destroyed ) { 00488 00489 // If mesh modification causes a ghost entity to become 00490 // a member of an owned-closure then do not automatically 00491 // destroy it. The new sharing status will be resolved 00492 // in 'internal_resolve_parallel_create'. 00493 00494 if ( ! in_owned_closure( *entity , m_parallel_rank ) ) { 00495 00496 const bool destroy_entity_successful = destroy_entity(entity); 00497 // Entity pointer is set to NULL: 00498 if ( ! destroy_entity_successful ) { 00499 throw std::logic_error("could not destroy ghost entity"); 00500 } 00501 } 00502 } 00503 } 00504 } // end loop on remote mod 00505 00506 // Erase all ghosting communication lists for: 00507 // 1) Destroyed entities. 00508 // 2) Owned and modified entities. 00509 00510 for ( std::vector<Entity*>::const_iterator 00511 i = entity_comm().end() ; i != entity_comm().begin() ; ) { 00512 00513 Entity & entity = **--i ; 00514 00515 const bool locally_destroyed = EntityLogDeleted == entity.log_query(); 00516 const bool locally_owned_and_modified = 00517 EntityLogModified == entity.log_query() && 00518 m_parallel_rank == entity.owner_rank() ; 00519 00520 if ( locally_destroyed || locally_owned_and_modified ) { 00521 00522 // m_ghosting[0] is the SHARED communication 00523 00524 for ( size_t j = ghosting_count ; j-- ; ) { 00525 if ( m_entity_repo.erase_ghosting( entity, *m_ghosting[j] ) ) { 00526 ghosting_change_flags[ j ] = true ; 00527 } 00528 } 00529 } 00530 } 00531 00532 std::vector< int > ghosting_change_flags_global( ghosting_count , 0 ); 00533 00534 all_reduce_sum( m_parallel_machine , 00535 & ghosting_change_flags[0] , 00536 & ghosting_change_flags_global[0] , 00537 ghosting_change_flags.size() ); 00538 00539 for ( unsigned ic = 0 ; ic < ghosting_change_flags_global.size() ; ++ic ) { 00540 if ( ghosting_change_flags_global[ic] ) { 00541 m_ghosting[ic]->m_sync_count = m_sync_count ; 00542 } 00543 } 00544 } 00545 00546 //---------------------------------------------------------------------- 00547 00548 00549 void BulkData::internal_resolve_parallel_create() 00550 { 00551 static const char method[] = 00552 "stk::mesh::BulkData::internal_resolve_parallel_create" ; 00553 00554 std::vector<Entity*> shared_modified ; 00555 00556 // Update the parallel index and 00557 // output shared and modified entities. 00558 internal_update_distributed_index( shared_modified ); 00559 00560 // A shared_modified entity which was not created this 00561 // cycle and is locally owned send claim on ownership 00562 // to the sharing processes. 00563 00564 { 00565 CommAll comm_all( m_parallel_machine ); 00566 00567 for ( std::vector<Entity*>::iterator 00568 i = shared_modified.begin() ; i != shared_modified.end() ; ++i ) { 00569 Entity & entity = **i ; 00570 if ( entity.owner_rank() == m_parallel_rank && 00571 entity.log_query() != EntityLogCreated ) { 00572 00573 for ( PairIterEntityComm 00574 jc = entity.sharing() ; ! jc.empty() ; ++jc ) { 00575 comm_all.send_buffer( jc->proc ) .pack<EntityKey>( entity.key() ); 00576 } 00577 } 00578 } 00579 00580 comm_all.allocate_buffers( m_parallel_size / 4 ); 00581 00582 for ( std::vector<Entity*>::iterator 00583 i = shared_modified.begin() ; i != shared_modified.end() ; ++i ) { 00584 Entity & entity = **i ; 00585 if ( entity.owner_rank() == m_parallel_rank && 00586 entity.log_query() != EntityLogCreated ) { 00587 00588 for ( PairIterEntityComm 00589 jc = entity.sharing() ; ! jc.empty() ; ++jc ) { 00590 comm_all.send_buffer( jc->proc ) .pack<EntityKey>( entity.key() ); 00591 } 00592 } 00593 } 00594 00595 comm_all.communicate(); 00596 00597 for ( unsigned p = 0 ; p < m_parallel_size ; ++p ) { 00598 CommBuffer & buf = comm_all.recv_buffer( p ); 00599 EntityKey key ; 00600 while ( buf.remaining() ) { 00601 buf.unpack<EntityKey>( key ); 00602 00603 Entity & entity = * get_entity( key ); 00604 00605 // Set owner, will correct part membership later 00606 m_entity_repo.set_entity_owner_rank( entity, p); 00607 } 00608 } 00609 } 00610 00611 // Update shared created entities. 00612 // - Revise ownership to selected processor 00613 // - Update sharing. 00614 // - Work backward so the 'in_owned_closure' function 00615 // can evaluate related higher ranking entities. 00616 00617 std::ostringstream error_msg ; 00618 int error_flag = 0 ; 00619 00620 PartVector shared_part , owned_part ; 00621 shared_part.push_back( & m_mesh_meta_data.globally_shared_part() ); 00622 owned_part.push_back( & m_mesh_meta_data.locally_owned_part() ); 00623 00624 for ( std::vector<Entity*>::const_iterator 00625 i = shared_modified.end() ; i != shared_modified.begin() ; ) { 00626 00627 Entity * entity = *--i ; 00628 00629 if ( entity->owner_rank() == m_parallel_rank && 00630 entity->log_query() == EntityLogCreated ) { 00631 00632 // Created and not claimed by an existing owner 00633 00634 const unsigned new_owner = determine_new_owner( *entity ); 00635 00636 m_entity_repo.set_entity_owner_rank( *entity, new_owner); 00637 } 00638 00639 if ( entity->owner_rank() != m_parallel_rank ) { 00640 // Do not own it and still have it. 00641 // Remove the locally owned, add the globally_shared 00642 m_entity_repo.set_entity_sync_count( *entity, m_sync_count); 00643 internal_change_entity_parts( *entity , shared_part , owned_part ); 00644 } 00645 else if ( ! entity->sharing().empty() ) { 00646 // Own it and has sharing information. 00647 // Add the globally_shared 00648 internal_change_entity_parts( *entity , shared_part , PartVector() ); 00649 } 00650 else { 00651 // Own it and does not have sharing information. 00652 // Remove the globally_shared 00653 internal_change_entity_parts( *entity , PartVector() , shared_part ); 00654 } 00655 00656 // Newly created shared entity had better be in the owned closure 00657 if ( ! in_owned_closure( *entity , m_parallel_rank ) ) { 00658 if ( 0 == error_flag ) { 00659 error_flag = 1 ; 00660 error_msg 00661 << std::endl 00662 << "P" << m_parallel_rank << ": " << method << " FAILED" 00663 << std::endl 00664 << " The following entities were declared on multiple processors," 00665 << std::endl 00666 << " cannot be parallel-shared, and were declared with" 00667 << " parallel-ghosting information. { " 00668 << std::endl ; 00669 } 00670 error_msg << " " ; 00671 print_entity_key( error_msg , m_mesh_meta_data , entity->key() ); 00672 error_msg << " also declared on" ; 00673 for ( PairIterEntityComm ec = entity->sharing(); ! ec.empty() ; ++ec ) { 00674 error_msg << " P" << ec->proc ; 00675 } 00676 error_msg << std::endl ; 00677 } 00678 } 00679 if ( error_flag ) { error_msg << "}" << std::endl ; } 00680 00681 all_reduce( m_parallel_machine , ReduceMax<1>( & error_flag ) ); 00682 00683 if ( error_flag ) { 00684 throw std::runtime_error( error_msg.str() ); 00685 } 00686 00687 const size_t n_old = m_entity_comm.size(); 00688 00689 m_entity_comm.insert( m_entity_comm.end() , 00690 shared_modified.begin() , shared_modified.end() ); 00691 00692 std::inplace_merge( m_entity_comm.begin() , 00693 m_entity_comm.begin() + n_old , 00694 m_entity_comm.end() , 00695 EntityLess() ); 00696 00697 { 00698 std::vector<Entity*>::iterator i = 00699 std::unique( m_entity_comm.begin() , m_entity_comm.end() ); 00700 00701 m_entity_comm.erase( i , m_entity_comm.end() ); 00702 } 00703 } 00704 00705 //---------------------------------------------------------------------- 00706 00707 bool BulkData::modification_end() 00708 { 00709 return internal_modification_end( true ); 00710 } 00711 00712 #if 0 00713 00714 namespace { 00715 00716 // Very, very handy for debugging parallel resolution... 00717 00718 void print_comm_list( const BulkData & mesh , bool doit ) 00719 { 00720 if ( doit ) { 00721 std::ostringstream msg ; 00722 00723 msg << std::endl ; 00724 00725 for ( std::vector<Entity*>::const_iterator 00726 i = mesh.entity_comm().begin() ; 00727 i != mesh.entity_comm().end() ; ++i ) { 00728 00729 Entity & entity = **i ; 00730 msg << "P" << mesh.parallel_rank() << ": " ; 00731 00732 print_entity_key( msg , mesh.mesh_meta_data() , entity.key() ); 00733 00734 msg << " owner(" << entity.owner_rank() << ")" ; 00735 00736 if ( EntityLogModified == entity.log_query() ) { msg << " mod" ; } 00737 else if ( EntityLogDeleted == entity.log_query() ) { msg << " del" ; } 00738 else { msg << " " ; } 00739 00740 for ( PairIterEntityComm ec = entity.comm(); ! ec.empty() ; ++ec ) { 00741 msg << " (" << ec->ghost_id << "," << ec->proc << ")" ; 00742 } 00743 msg << std::endl ; 00744 } 00745 00746 std::cout << msg.str(); 00747 } 00748 } 00749 00750 } 00751 00752 #endif 00753 00754 bool BulkData::internal_modification_end( bool regenerate_aura ) 00755 { 00756 if ( m_sync_state == SYNCHRONIZED ) { return false ; } 00757 00758 // Resolve modification or deletion of shared entities 00759 // which can cause deletion of ghost entities. 00760 internal_resolve_shared_modify_delete(); 00761 00762 // Resolve modification or deletion of ghost entities 00763 // by destroying ghost entities that have been touched. 00764 internal_resolve_ghosted_modify_delete(); 00765 00766 // Resolution of shared and ghost modifications can empty 00767 // the communication information for entities. 00768 // If their is no communication information then the 00769 // entity must be removed from the communication list. 00770 { 00771 std::vector<Entity*>::iterator i = m_entity_comm.begin(); 00772 bool changed = false ; 00773 for ( ; i != m_entity_comm.end() ; ++i ) { 00774 if ( (*i)->comm().empty() ) { *i = NULL ; changed = true ; } 00775 } 00776 if ( changed ) { 00777 i = std::remove( m_entity_comm.begin() , 00778 m_entity_comm.end() , (Entity *) NULL ); 00779 m_entity_comm.erase( i , m_entity_comm.end() ); 00780 } 00781 } 00782 00783 // Resolve creation of entities: discover sharing and set unique ownership. 00784 internal_resolve_parallel_create(); 00785 00786 // Resolve part membership for shared entities. 00787 // This occurs after resolving creation so created and shared 00788 // entities are resolved along with previously existing shared entities. 00789 internal_resolve_shared_membership(); 00790 00791 // Regenerate the ghosting aura around all shared mesh entities. 00792 if ( regenerate_aura ) { internal_regenerate_shared_aura(); } 00793 00794 // ------------------------------ 00795 // Verify parallel consistency of mesh entities. 00796 // Unique ownership, communication lists, sharing part membership, 00797 // application part membership consistency. 00798 { 00799 std::ostringstream msg ; 00800 if ( ! comm_mesh_verify_parallel_consistency( *this , msg ) ) { 00801 std::cerr << msg.str() << std::endl ; 00802 throw std::runtime_error( msg.str() ); 00803 } 00804 } 00805 // ------------------------------ 00806 // The very last operation performed is to sort the bucket entities. 00807 // This does not change the entities, relations, or field data. 00808 // However, it insures that the ordering of entities and buckets 00809 // is independent of the order in which a set of changes were 00810 // performed. 00811 00812 m_bucket_repository.internal_sort_bucket_entities(); 00813 00814 // ------------------------------ 00815 00816 m_sync_state = SYNCHRONIZED ; 00817 00818 return true ; 00819 } 00820 00821 //---------------------------------------------------------------------- 00822 //---------------------------------------------------------------------- 00823 00824 enum { PART_ORD_UNIVERSAL = 0 }; 00825 enum { PART_ORD_OWNED = 1 }; 00826 enum { PART_ORD_SHARED = 2 }; 00827 00828 namespace { 00829 00830 void pack_induced_memberships( CommAll & comm , 00831 const std::vector<Entity*> & entity_comm ) 00832 { 00833 for ( std::vector<Entity*>::const_iterator 00834 i = entity_comm.begin() ; i != entity_comm.end() ; ++i ) { 00835 00836 Entity & entity = **i ; 00837 00838 if ( in_shared( entity , entity.owner_rank() ) ) { 00839 // Is shared with owner, send to owner. 00840 00841 PartVector empty , induced ; 00842 00843 induced_part_membership( entity , empty , induced ); 00844 00845 CommBuffer & buf = comm.send_buffer( entity.owner_rank() ); 00846 00847 unsigned tmp = induced.size(); 00848 00849 buf.pack<unsigned>( tmp ); 00850 00851 for ( PartVector::iterator 00852 j = induced.begin() ; j != induced.end() ; ++j ) { 00853 tmp = (*j)->mesh_meta_data_ordinal(); 00854 buf.pack<unsigned>( tmp ); 00855 } 00856 } 00857 } 00858 } 00859 00860 void generate_send_list( const size_t sync_count , 00861 const unsigned p_rank , 00862 const std::vector<Entity*> & entity_comm , 00863 std::vector<EntityProc> & send_list ) 00864 { 00865 for ( std::vector<Entity*>::const_iterator 00866 i = entity_comm.begin() ; i != entity_comm.end() ; ++i ) { 00867 00868 Entity & entity = **i ; 00869 00870 if ( entity.owner_rank() == p_rank && 00871 entity.synchronized_count() == sync_count ) { 00872 00873 for ( PairIterEntityComm ec = entity.comm() ; ! ec.empty() ; ++ec ) { 00874 EntityProc tmp( & entity , ec->proc ); 00875 send_list.push_back( tmp ); 00876 } 00877 } 00878 } 00879 00880 { 00881 std::sort( send_list.begin() , send_list.end() , EntityLess() ); 00882 std::vector<EntityProc>::iterator i = 00883 std::unique( send_list.begin() , send_list.end() ); 00884 send_list.erase( i , send_list.end() ); 00885 } 00886 } 00887 00888 void pack_part_memberships( CommAll & comm , 00889 const std::vector<EntityProc> & send_list ) 00890 { 00891 for ( std::vector<EntityProc>::const_iterator 00892 i = send_list.begin() ; i != send_list.end() ; ++i ) { 00893 00894 Entity & entity = * i->first ; 00895 00896 std::pair<const unsigned *, const unsigned *> 00897 part_ord = entity.bucket().superset_part_ordinals(); 00898 00899 // I am the owner; therefore, the first three members are 00900 // universal, uses, and owns. Don't send them. 00901 00902 // I am the owner. The first two memberships are 00903 // universal_part and locally_owned_part. The third 00904 // membership may be globally_shared_part ; 00905 00906 const unsigned count_all = part_ord.second - part_ord.first ; 00907 const unsigned count_skip = 00908 ( 2 < count_all && part_ord.first[2] == PART_ORD_SHARED ) ? 3 : 2 ; 00909 00910 const unsigned count_send = count_all - count_skip ; 00911 00912 const unsigned * const start_send = part_ord.first + count_skip ; 00913 00914 comm.send_buffer( i->second ).pack<EntityKey>( entity.key() ) 00915 .pack<unsigned>( count_send ) 00916 .pack<unsigned>( start_send , count_send ); 00917 } 00918 } 00919 00920 } 00921 00922 // Mesh entity membership changes must be synchronized among 00923 // processes that share mesh entities and propagated to 00924 // processes that ghost copies of the mesh entities. 00925 // 00926 // Precondition: correct shared and ghosting lists. 00927 // 00928 // Part memberships may have been added or removed 00929 // either explicitly or indirectly via entity relationships 00930 // being added or removed. 00931 00932 void BulkData::internal_resolve_shared_membership() 00933 { 00934 static const char method[] = 00935 "stk::mesh::BulkData::internal_resolve_shared_membership" ; 00936 00937 const MetaData & meta = m_mesh_meta_data ; 00938 ParallelMachine p_comm = m_parallel_machine ; 00939 const unsigned p_rank = m_parallel_rank ; 00940 const unsigned p_size = m_parallel_size ; 00941 const PartVector & all_parts = meta.get_parts(); 00942 00943 const Part & part_universal = meta.universal_part(); 00944 const Part & part_owned = meta.locally_owned_part(); 00945 const Part & part_shared = meta.globally_shared_part(); 00946 00947 // Quick verification of part ordinal assumptions 00948 00949 if ( PART_ORD_UNIVERSAL != part_universal.mesh_meta_data_ordinal() || 00950 PART_ORD_OWNED != part_owned.mesh_meta_data_ordinal() || 00951 PART_ORD_SHARED != part_shared.mesh_meta_data_ordinal() ) { 00952 throw std::logic_error( std::string( method ) ); 00953 } 00954 00955 // Shared entities may have been modified due to relationship changes. 00956 // Send just the current induced memberships from the sharing to 00957 // the owning processes. 00958 { 00959 CommAll comm( p_comm ); 00960 00961 pack_induced_memberships( comm , m_entity_comm ); 00962 00963 comm.allocate_buffers( p_size / 4 ); 00964 00965 pack_induced_memberships( comm , m_entity_comm ); 00966 00967 comm.communicate(); 00968 00969 for ( std::vector<Entity*>::iterator 00970 i = m_entity_comm.begin() ; i != m_entity_comm.end() ; ++i ) { 00971 00972 Entity & entity = **i ; 00973 00974 if ( entity.owner_rank() == p_rank ) { 00975 // Receiving from all sharing processes 00976 00977 PartVector empty , induced_parts , current_parts , remove_parts ; 00978 00979 induced_part_membership( entity , empty , induced_parts ); 00980 00981 for ( PairIterEntityComm 00982 ec = entity.sharing() ; ! ec.empty() ; ++ec ) { 00983 00984 CommBuffer & buf = comm.recv_buffer( ec->proc ); 00985 00986 unsigned count = 0 ; buf.unpack<unsigned>( count ); 00987 for ( unsigned j = 0 ; j < count ; ++j ) { 00988 unsigned part_ord = 0 ; buf.unpack<unsigned>( part_ord ); 00989 insert( induced_parts , * all_parts[ part_ord ] ); 00990 } 00991 } 00992 00993 // Remove any part that is an induced part but is not 00994 // in the induced parts list. 00995 00996 entity.bucket().supersets( current_parts ); 00997 00998 for ( PartVector::iterator 00999 p = current_parts.begin() ; p != current_parts.end() ; ++p ) { 01000 if ( membership_is_induced( **p , entity.entity_rank() ) && 01001 ! contain( induced_parts , **p ) ) { 01002 remove_parts.push_back( *p ); 01003 } 01004 } 01005 01006 internal_change_entity_parts( entity, induced_parts, remove_parts ); 01007 } 01008 } 01009 } 01010 01011 //------------------------------ 01012 // The owners have complete knowledge of memberships. 01013 // Send membership information to sync the shared and ghosted copies. 01014 // Only need to do this for entities that have actually changed. 01015 01016 { 01017 std::vector<EntityProc> send_list ; 01018 01019 generate_send_list( m_sync_count, p_rank, m_entity_comm, send_list); 01020 01021 CommAll comm( p_comm ); 01022 01023 pack_part_memberships( comm , send_list ); 01024 01025 comm.allocate_buffers( p_size / 4 ); 01026 01027 pack_part_memberships( comm , send_list ); 01028 01029 comm.communicate(); 01030 01031 for ( unsigned p = 0 ; p < p_size ; ++p ) { 01032 CommBuffer & buf = comm.recv_buffer( p ); 01033 while ( buf.remaining() ) { 01034 01035 PartVector owner_parts , current_parts , remove_parts ; 01036 01037 EntityKey key ; buf.unpack<EntityKey>( key ); 01038 unsigned count = 0 ; buf.unpack<unsigned>( count ); 01039 for ( unsigned j = 0 ; j < count ; ++j ) { 01040 unsigned part_ord = 0 ; buf.unpack<unsigned>( part_ord ); 01041 insert( owner_parts , * all_parts[ part_ord ] ); 01042 } 01043 01044 // Any current part that is not a member of owners_parts 01045 // must be removed. 01046 01047 Entity * const entity = find_entity(m_entity_comm, key, true); 01048 01049 entity->bucket().supersets( current_parts ); 01050 01051 for ( PartVector::iterator 01052 ip = current_parts.begin() ; ip != current_parts.end() ; ++ip ) { 01053 Part * const part = *ip ; 01054 const unsigned part_ord = part->mesh_meta_data_ordinal(); 01055 if ( PART_ORD_UNIVERSAL != part_ord && 01056 PART_ORD_OWNED != part_ord && 01057 PART_ORD_SHARED != part_ord && 01058 ! contain( owner_parts , *part ) ) { 01059 remove_parts.push_back( part ); 01060 } 01061 } 01062 01063 internal_change_entity_parts( *entity , owner_parts , remove_parts ); 01064 } 01065 } 01066 } 01067 } 01068 01069 } // namespace mesh 01070 } // namespace stk 01071