Sierra Toolkit Version of the Day
BulkDataEndSync.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 
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends