Sierra Toolkit Version of the Day
BulkDataOwner.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 #include <stdexcept>
00014 #include <iostream>
00015 #include <sstream>
00016 #include <set>
00017 #include <vector>
00018 #include <algorithm>
00019 
00020 #include <stk_util/parallel/ParallelComm.hpp>
00021 #include <stk_util/parallel/ParallelReduce.hpp>
00022 
00023 #include <stk_mesh/base/BulkData.hpp>
00024 #include <stk_mesh/base/MetaData.hpp>
00025 #include <stk_mesh/base/Entity.hpp>
00026 #include <stk_mesh/base/EntityComm.hpp>
00027 #include <stk_mesh/base/Bucket.hpp>
00028 
00029 namespace stk {
00030 namespace mesh {
00031 
00032 //----------------------------------------------------------------------
00033 
00034 namespace {
00035 
00036 void insert_closure_ghost( Entity * const entity ,
00037                            const unsigned proc_local ,
00038                            std::set<Entity*,EntityLess> & remove_list )
00039 {
00040   if ( ! in_owned_closure( *entity , proc_local ) ) {
00041     // This entity is a ghost, put it on the remove_list
00042     // along with all ghosts in its closure
00043 
00044     std::pair< std::set<Entity*,EntityLess>::iterator , bool >
00045       result = remove_list.insert( entity );
00046 
00047     if ( result.second ) {
00048       // This ghost entity is new to the list, traverse its closure.
00049 
00050       const unsigned etype = entity->entity_rank();
00051 
00052       for ( PairIterRelation
00053             irel = entity->relations() ; ! irel.empty() ; ++irel ) {
00054 
00055         if ( irel->entity_rank() < etype ) {
00056           insert_closure_ghost( irel->entity() , proc_local ,remove_list );
00057         }
00058       }
00059     }
00060   }
00061 }
00062 
00063 void insert_transitive_ghost( Entity * const entity ,
00064                               const unsigned proc_local ,
00065                               std::set<Entity*,EntityLess> & remove_list )
00066 {
00067   insert_closure_ghost( entity , proc_local , remove_list );
00068 
00069   // Transitive:
00070   // If this entity is a member of another entity's closure
00071   // then that other entity is part of the traversal.
00072 
00073   const unsigned etype = entity->entity_rank();
00074 
00075   for ( PairIterRelation rel = entity->relations(); ! rel.empty() ; ++rel ) {
00076     if ( etype < rel->entity_rank() ) {
00077       insert_transitive_ghost( rel->entity() , proc_local , remove_list );
00078     }
00079   }
00080 }
00081 
00082 //----------------------------------------------------------------------
00083 
00084 void insert_closure_send(
00085   const EntityProc                  send_entry ,
00086   std::set<EntityProc,EntityLess> & send_list )
00087 {
00088   if ( EntityLogDeleted == send_entry.first->log_query() ) {
00089     throw std::logic_error( std::string("Cannot send destroyed entity") );
00090   }
00091 
00092   std::pair< std::set<EntityProc,EntityLess>::iterator , bool >
00093     result = send_list.insert( send_entry );
00094 
00095   if ( result.second ) {
00096     // First time this entity was inserted into the send_list.
00097 
00098     const unsigned erank  = send_entry.first->entity_rank();
00099     PairIterRelation irel = send_entry.first->relations();
00100 
00101     for ( ; ! irel.empty() ; ++irel ) {
00102       if ( irel->entity_rank() < erank ) {
00103         const EntityProc rel_send_entry( irel->entity(), send_entry.second );
00104 
00105         insert_closure_send( rel_send_entry , send_list );
00106       }
00107     }
00108   }
00109 }
00110 
00111 //----------------------------------------------------------------------
00112 
00113 bool member_of_owned_closure( const Entity & e , const unsigned p_rank )
00114 {
00115   bool result = p_rank == e.owner_rank();
00116 
00117   const unsigned etype = e.entity_rank();
00118 
00119   // Any higher ranking entities locally owned?
00120   for ( PairIterRelation
00121         irel = e.relations(); ! result && ! irel.empty() ; ++irel ) {
00122     result = etype  <  irel->entity_rank() &&
00123              p_rank == irel->entity()->owner_rank();
00124   }
00125 
00126   // Any higher ranking entity member of an owned closure?
00127   for ( PairIterRelation
00128         irel = e.relations(); ! result && ! irel.empty() ; ++irel ) {
00129     result = etype < irel->entity_rank() &&
00130              member_of_owned_closure( * irel->entity() , p_rank );
00131   }
00132 
00133   return result ;
00134 }
00135 
00136 //----------------------------------------------------------------------
00137 
00138 void clean_and_verify_parallel_change(
00139   const char method[] ,
00140   const BulkData & mesh ,
00141   std::vector<EntityProc> & local_change )
00142 {
00143   const MetaData      & meta   = mesh.mesh_meta_data() ;
00144   const unsigned        p_rank = mesh.parallel_rank();
00145   const unsigned        p_size = mesh.parallel_size();
00146   const ParallelMachine p_comm = mesh.parallel();
00147 
00148   size_t error_count = 0 ;
00149 
00150   std::ostringstream error_msg ;
00151 
00152   // Order and eliminate redundancies:
00153   {
00154     std::vector<EntityProc>::iterator i = local_change.begin() ,
00155                                       j = local_change.end() ;
00156     std::sort( i , j , EntityLess() );
00157     i = std::unique( i , j );
00158     local_change.erase( i , j );
00159   }
00160 
00161   for ( std::vector<EntityProc>::iterator
00162         i = local_change.begin() ; i != local_change.end() ; ) {
00163     std::vector<EntityProc>::iterator j = i ; ++i ;
00164     Entity * const entity    = j->first ;
00165     const unsigned new_owner = j->second ;
00166 
00167     // Verification:
00168     // 1) If bucket has no capacity then is destined for deletion
00169     // 2) If not locally owned then not allowed grant ownership
00170     // 3) New owner must be legit
00171     // 4) Cannot grant to two different owners
00172 
00173     const bool bad_null   = NULL == entity ;
00174     const bool bad_delete = ! bad_null && EntityLogDeleted == entity->log_query();
00175     const bool bad_entity = ! bad_null && entity->owner_rank() != p_rank ;
00176     const bool bad_owner  = p_size <= new_owner ;
00177     const bool bad_dup    = ! bad_null && i != local_change.end() && entity == i->first ;
00178 
00179     if ( bad_null || bad_entity || bad_owner || bad_dup || bad_delete ) {
00180       ++error_count ;
00181 
00182       error_msg << "  P" << p_rank << ": " ;
00183       if ( bad_null ) { error_msg << " NULL ENTITY" ; }
00184       else { print_entity_key( error_msg , meta , entity->key() ); }
00185       if ( bad_delete ) { error_msg << " HAS_BEEN_DELETED" ; }
00186       if ( bad_entity ) { error_msg << " NOT_CURRENT_OWNER" ; }
00187       if ( bad_owner ) {
00188         error_msg << " BAD_NEW_OWNER( " << new_owner << " )" ;
00189       }
00190       if ( bad_dup ) {
00191         error_msg << " CONFLICTING_NEW_OWNER( " << new_owner ;
00192         error_msg << " != " << i->second << " )" ;
00193       }
00194       error_msg << std::endl ;
00195     }
00196     else if ( new_owner == p_rank ) {
00197       // Eliminate non-changes
00198       j->first = NULL ;
00199       j->second = 0 ;
00200     }
00201   }
00202 
00203   all_reduce( p_comm , ReduceSum<1>( & error_count ) );
00204 
00205   if ( error_count ) {
00206     std::string msg_throw ;
00207     msg_throw.append( method );
00208     msg_throw.append( " FAILED: Bad change ownership directives" );
00209 
00210     if ( 0 == p_rank ) { std::cerr << msg_throw ; }
00211 
00212     all_write_string( p_comm , std::cerr , error_msg.str() );
00213 
00214     throw std::runtime_error( msg_throw );
00215   }
00216 
00217   {
00218     std::vector<EntityProc>::iterator i = local_change.begin(),
00219                                       j = local_change.end();
00220     i = std::remove( i , j , EntityProc(NULL,0) );
00221     local_change.erase( i , j );
00222   }
00223 }
00224 
00225 //----------------------------------------------------------------------
00226 // Generate a parallel consistent list of ownership changes:
00227 // 1) Shared entities (not owned but in closure of an owned entity),
00228 // 2) Ghosted entities (not owned and not in closure of an owned entity), and
00229 // 3) Parallel index.
00230 
00231 void generate_parallel_change( const BulkData & mesh ,
00232                                const std::vector<EntityProc> & local_change ,
00233                                      std::vector<EntityProc> & shared_change ,
00234                                      std::vector<EntityProc> & ghosted_change )
00235 {
00236   const unsigned p_size = mesh.parallel_size();
00237 
00238   CommAll comm( mesh.parallel() );
00239 
00240   // Sizing:
00241 
00242   std::vector<unsigned> procs ;
00243 
00244   for ( std::vector<EntityProc>::const_iterator
00245         ip = local_change.begin() ; ip != local_change.end() ; ++ip ) {
00246     Entity & entity = * ip->first ;
00247     comm_procs( entity , procs );
00248     for ( std::vector<unsigned>::iterator
00249            j = procs.begin() ; j != procs.end() ; ++j ) {
00250       comm.send_buffer( *j ).skip<EntityKey>(1).skip<unsigned>(1);
00251     }
00252   }
00253 
00254   // Allocation:
00255 
00256   comm.allocate_buffers( p_size / 4 , 0 );
00257 
00258   // Packing new owner info:
00259 
00260   for ( std::vector<EntityProc>::const_iterator
00261         ip = local_change.begin() ; ip != local_change.end() ; ++ip ) {
00262     Entity & entity = * ip->first ;
00263     comm_procs( entity , procs );
00264     for ( std::vector<unsigned>::iterator
00265            j = procs.begin() ; j != procs.end() ; ++j ) {
00266       comm.send_buffer( *j )
00267           .pack<EntityKey>( entity.key() )
00268           .pack<unsigned>(  ip->second );
00269     }
00270   }
00271 
00272   comm.communicate();
00273 
00274   for ( unsigned ip = 0 ; ip < p_size ; ++ip ) {
00275     CommBuffer & buf = comm.recv_buffer( ip );
00276     while ( buf.remaining() ) {
00277       EntityProc entry ;
00278       EntityKey key ;
00279       buf.unpack<EntityKey>( key )
00280          .unpack<unsigned>( entry.second );
00281 
00282       entry.first = mesh.get_entity( key );
00283 
00284       if ( in_receive_ghost( * entry.first ) ) {
00285         ghosted_change.push_back( entry );
00286       }
00287       else {
00288         shared_change.push_back( entry );
00289       }
00290     }
00291   }
00292 
00293   std::sort( shared_change.begin() , shared_change.end() , EntityLess() );
00294   std::sort( ghosted_change.begin() , ghosted_change.end() , EntityLess() );
00295 }
00296 
00297 }
00298 
00299 //----------------------------------------------------------------------
00300 //----------------------------------------------------------------------
00301 
00302 void BulkData::change_entity_owner( const std::vector<EntityProc> & arg_change )
00303 {
00304   static const char method[] = "stk::mesh::BulkData::change_entity_owner" ;
00305 
00306   const MetaData  & meta = m_mesh_meta_data ;
00307   const unsigned  p_rank = m_parallel_rank ;
00308   const unsigned  p_size = m_parallel_size ;
00309   ParallelMachine p_comm = m_parallel_machine ;
00310 
00311   //------------------------------
00312   // Verify the input changes, generate a clean local change list, and
00313   // generate the remote change list so that all processes know about
00314   // pending changes.
00315 
00316   std::vector<EntityProc> local_change( arg_change );
00317 
00318   // Parallel synchronous clean up and verify the requested changes:
00319   clean_and_verify_parallel_change( method , *this , local_change );
00320 
00321   //----------------------------------------
00322   // Parallel synchronous determination of changing
00323   // shared and ghosted.
00324 
00325   std::vector<EntityProc> ghosted_change ;
00326   std::vector<EntityProc> shared_change ;
00327 
00328   generate_parallel_change( *this , local_change ,
00329                             shared_change , ghosted_change );
00330 
00331   //------------------------------
00332   // Have enough information to delete all effected ghosts.
00333   // If the closure of a ghost contains a changing entity
00334   // then that ghost must be deleted.
00335   // Request that all ghost entities in the closure of the ghost be deleted.
00336 
00337   typedef std::set<EntityProc,EntityLess> EntityProcSet;
00338   typedef std::set<Entity*,EntityLess> EntitySet;
00339 
00340   // Closure of the owner change for impacted ghost entities.
00341 
00342   EntityProcSet send_closure ;
00343 
00344   for ( std::vector<EntityProc>::iterator
00345         i = local_change.begin() ; i != local_change.end() ; ++i ) {
00346     insert_closure_send( *i , send_closure );
00347   }
00348 
00349   {
00350     EntitySet work ;
00351 
00352     for ( std::vector<EntityProc>::const_iterator
00353           i = ghosted_change.begin() ; i != ghosted_change.end() ; ++i ) {
00354       insert_transitive_ghost( i->first , m_parallel_rank , work );
00355     }
00356 
00357     for ( std::vector<EntityProc>::const_iterator
00358           i = shared_change.begin() ; i != shared_change.end() ; ++i ) {
00359       insert_transitive_ghost( i->first , m_parallel_rank , work );
00360     }
00361 
00362     for ( EntityProcSet::iterator
00363           i = send_closure.begin() ; i != send_closure.end() ; ++i ) {
00364       insert_transitive_ghost( i->first , m_parallel_rank , work );
00365     }
00366 
00367     // The ghosted change list will become invalid
00368     ghosted_change.clear();
00369 
00370     std::vector<EntityProc> empty ;
00371     std::vector<Entity*> effected_ghosts( work.begin() , work.end() );
00372 
00373     // Skip 'm_ghosting[0]' which is the shared subset.
00374     for ( std::vector<Ghosting*>::iterator
00375           ig = m_ghosting.begin() + 1 ; ig != m_ghosting.end() ; ++ig ) {
00376       // parallel synchronous:
00377       internal_change_ghosting( **ig , empty , effected_ghosts );
00378     }
00379   }
00380 
00381   //------------------------------
00382   // Consistently change the owner on all processes.
00383   // 1) The local_change list is giving away ownership.
00384   // 2) The shared_change may or may not be receiving ownership
00385 
00386   {
00387     PartVector owned( 1 );
00388     owned[0] = & meta.locally_owned_part();
00389 
00390     for ( std::vector<EntityProc>::iterator
00391           i = local_change.begin() ; i != local_change.end() ; ++i ) {
00392       // Giving ownership, change the parts first and then
00393       // the owner rank to pass the ownership test.
00394       change_entity_parts( * i->first , PartVector() , owned );
00395 
00396       m_entity_repo.set_entity_owner_rank( *(i->first), i->second);
00397     }
00398 
00399     for ( std::vector<EntityProc>::iterator
00400           i = shared_change.begin() ; i != shared_change.end() ; ++i ) {
00401       m_entity_repo.set_entity_owner_rank( *(i->first), i->second);
00402       if ( p_rank == i->second ) { // I receive ownership
00403         change_entity_parts( * i->first , owned , PartVector() );
00404       }
00405     }
00406   }
00407 
00408   //------------------------------
00409   // Send entities, along with their closure, to the new owner processes
00410   {
00411     std::ostringstream error_msg ;
00412     int error_count = 0 ;
00413 
00414     CommAll comm( p_comm );
00415 
00416     for ( std::set<EntityProc,EntityLess>::iterator
00417           i = send_closure.begin() ; i != send_closure.end() ; ++i ) {
00418       CommBuffer & buffer = comm.send_buffer( i->second );
00419       Entity     & entity = * i->first ;
00420       pack_entity_info( buffer , entity );
00421       pack_field_values( buffer , entity );
00422     }
00423 
00424     comm.allocate_buffers( p_size / 4 );
00425 
00426     for ( std::set<EntityProc,EntityLess>::iterator
00427           i = send_closure.begin() ; i != send_closure.end() ; ++i ) {
00428       CommBuffer & buffer = comm.send_buffer( i->second );
00429       Entity     & entity = * i->first ;
00430       pack_entity_info( buffer , entity );
00431       pack_field_values( buffer , entity );
00432     }
00433 
00434     comm.communicate();
00435 
00436     for ( unsigned p = 0 ; p < p_size ; ++p ) {
00437       CommBuffer & buf = comm.recv_buffer(p);
00438       while ( buf.remaining() ) {
00439         PartVector parts ;
00440         std::vector<Relation> relations ;
00441         EntityKey key ;
00442         unsigned  owner = ~0u ;
00443 
00444         unpack_entity_info( buf, *this, key, owner, parts, relations );
00445 
00446         // Received entity information will be correct,
00447         // modulo the owned and shared parts
00448 
00449         remove( parts , meta.globally_shared_part() );
00450 
00451         if ( owner == p_rank ) {
00452           // Must have the locally_owned_part
00453           insert( parts , meta.locally_owned_part() );
00454         }
00455         else {
00456           // Must not have the locally_owned_part
00457           remove( parts , meta.locally_owned_part() );
00458         }
00459 
00460         std::pair<Entity*,bool> result =
00461           m_entity_repo.internal_create_entity( key );
00462 
00463         m_entity_repo.log_created_parallel_copy( *(result.first) );
00464 
00465         // The entity was copied and not created.
00466 
00467         m_entity_repo.set_entity_owner_rank( *(result.first), owner);
00468 
00469         internal_change_entity_parts( *result.first , parts , PartVector() );
00470 
00471         declare_relation( *result.first , relations );
00472 
00473         if ( ! unpack_field_values( buf , * result.first , error_msg ) ) {
00474           ++error_count ;
00475         }
00476       }
00477     }
00478 
00479     all_reduce( p_comm , ReduceSum<1>( & error_count ) );
00480 
00481     if ( error_count ) { throw std::runtime_error( error_msg.str() ); }
00482 
00483     // Any entity that I sent and is not in an owned closure is deleted.
00484     // The owned closure will be effected by received entities, so can
00485     // only clean up after the newly owned entities have been received.
00486     // Destroy backwards so as not to invalidate closures in the process.
00487 
00488     {
00489       Entity * entity = NULL ;
00490 
00491       for ( std::set<EntityProc,EntityLess>::iterator
00492             i = send_closure.end() ; i != send_closure.begin() ; ) {
00493 
00494         Entity * e = (--i)->first ;
00495 
00496         // The same entity may be sent to more than one process.
00497         // Only evaluate it once.
00498 
00499         if ( entity != e ) {
00500           entity = e ;
00501           if ( ! member_of_owned_closure( *e , p_rank ) ) {
00502             if ( ! destroy_entity( e ) ) {
00503               throw std::logic_error(std::string("BulkData::destroy_entity FAILED"));
00504             }
00505           }
00506         }
00507       }
00508     }
00509 
00510     send_closure.clear(); // Has been invalidated
00511   }
00512 }
00513 
00514 //----------------------------------------------------------------------
00515 
00516 } // namespace mesh
00517 } // namespace stk
00518 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends