Sierra Toolkit Version of the Day
BulkModification.cpp
00001 /*------------------------------------------------------------------------*/
00002 /*                 Copyright 2010 Sandia Corporation.                     */
00003 /*  Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive   */
00004 /*  license for use of this work by or on behalf of the U.S. Government.  */
00005 /*  Export of this program may require a license from the                 */
00006 /*  United States Government.                                             */
00007 /*------------------------------------------------------------------------*/
00008 
00009 #include <set>
00010 #include <stdexcept>
00011 #include <sstream>
00012 
00013 #include <stk_util/parallel/ParallelComm.hpp>
00014 
00015 #include <stk_mesh/base/BulkModification.hpp>
00016 
00017 #include <stk_mesh/base/BulkData.hpp>
00018 #include <stk_mesh/base/Entity.hpp>
00019 #include <stk_mesh/base/EntityComm.hpp>
00020 
00021 
00022 namespace stk {
00023 namespace mesh {
00024 
00025 typedef std::set<Entity *, EntityLess> EntitySet;
00026 typedef std::set<EntityProc , EntityLess> EntityProcSet;
00027 
00028 namespace {
00029 
00030 void construct_transitive_closure( EntitySet & closure , Entity & entry )
00031 {
00032 
00033   std::pair< EntitySet::const_iterator , bool >
00034     result = closure.insert( & entry );
00035 
00036   // A new insertion, must also insert the closure
00037   if ( result.second ) {
00038 
00039     const unsigned erank = entry.entity_rank();
00040     PairIterRelation irel  = entry.relations();
00041 
00042     for ( ; irel.first != irel.second ; ++irel.first ) {
00043       // insert entities with relations of lower rank into the closure
00044       if ( irel.first->entity_rank() < erank ) {
00045         Entity * tmp = irel.first->entity();
00046         construct_transitive_closure( closure , *tmp );
00047       }
00048     }
00049   }
00050 }
00051 
00052 void find_local_closure ( EntitySet & closure, const EntityVector & entities)
00053 {
00054   for (EntityVector::const_iterator i = entities.begin();
00055       i != entities.end(); ++i)
00056   {
00057     construct_transitive_closure(closure, **i);
00058   }
00059 }
00060 
00061 void construct_communication_set( const BulkData & bulk, const EntitySet & closure, EntityProcSet & communication_set)
00062 {
00063   if (bulk.parallel_size() < 2) return;
00064 
00065   for ( EntitySet::const_iterator
00066         i = closure.begin(); i != closure.end(); ++i) {
00067 
00068     Entity & entity = **i;
00069 
00070     const bool owned = bulk.parallel_rank() == entity.owner_rank();
00071 
00072     // Add sharing processes and ghost-send processes to communication_set
00073 
00074     for ( PairIterEntityComm ec = entity.comm(); ! ec.empty() ; ++ec ) {
00075       if ( owned || ec->ghost_id == 0 ) {
00076         EntityProc tmp( & entity , ec->proc );
00077         communication_set.insert( tmp );
00078       }
00079     }
00080   }
00081 }
00082 
00083 size_t count_non_used_entities( const BulkData & bulk, const EntityVector & entities)
00084 {
00085   const unsigned proc_local = bulk.parallel_rank();
00086   size_t non_used_entities = 0;
00087 
00088   for ( EntityVector::const_iterator
00089         i = entities.begin(); i != entities.end(); ++i ) {
00090     if ( ! in_owned_closure( **i , proc_local ) ) {
00091       ++non_used_entities;
00092     }
00093   }
00094 
00095   return non_used_entities;
00096 }
00097 
00098 }
00099 
00100 
00101 
00102 void find_closure( const BulkData & bulk,
00103     const std::vector< Entity *> & entities,
00104     std::vector< Entity *> & entities_closure)
00105 {
00106 
00107   entities_closure.clear();
00108 
00109 
00110   EntityProcSet send_list;
00111   EntitySet     temp_entities_closure;
00112 
00113   const bool bulk_not_synchronized = bulk.synchronized_state() != BulkData::SYNCHRONIZED;
00114   const size_t non_used_entities = bulk_not_synchronized ? 0 : count_non_used_entities(bulk, entities);
00115 
00116   const bool local_bad_input = bulk_not_synchronized || (0 < non_used_entities);
00117 
00118   //Can skip if error on input
00119   if ( !local_bad_input) {
00120 
00121     find_local_closure(temp_entities_closure, entities);
00122 
00123     construct_communication_set(bulk, temp_entities_closure, send_list);
00124   }
00125 
00126 
00127   CommAll all( bulk.parallel() );
00128 
00129   //pack send_list for sizing
00130   for ( EntityProcSet::const_iterator
00131       ep = send_list.begin() ; ep != send_list.end() ; ++ep ) {
00132     all.send_buffer( ep->second).pack<EntityKey>(ep->first->key());
00133   }
00134 
00135 
00136   const bool global_bad_input = all.allocate_buffers( bulk.parallel_size() / 4 , false, local_bad_input );
00137 
00138   if (global_bad_input) {
00139 
00140     std::ostringstream msg;
00141     //parallel consisent throw
00142     if (bulk_not_synchronized) {
00143       msg << "stk::mesh::find_closure( const BulkData & bulk, ... ) bulk is not synchronized";
00144     }
00145     else if ( 0 < non_used_entities) {
00146       msg << "stk::mesh::find_closure( const BulkData & bulk, std::vector<Entity *> entities, ... ) \n"
00147           << "entities contains " << non_used_entities << " non locally used entities \n";
00148     }
00149 
00150     throw std::runtime_error(msg.str());
00151   }
00152 
00153 
00154   //pack send_list
00155   for ( EntityProcSet::const_iterator
00156       ep = send_list.begin() ; ep != send_list.end() ; ++ep ) {
00157     all.send_buffer( ep->second).pack<EntityKey>(ep->first->key());
00158   }
00159 
00160 
00161   all.communicate();
00162 
00163   //unpack the send_list into the temp entities closure set
00164   for ( unsigned p = 0 ; p < bulk.parallel_size() ; ++p ) {
00165     CommBuffer & buf = all.recv_buffer( p );
00166     EntityKey k ;
00167     while ( buf.remaining() ) {
00168       buf.unpack<EntityKey>( k );
00169       Entity * e = bulk.get_entity(k);
00170       temp_entities_closure.insert(e);
00171     }
00172   }
00173 
00174   //copy the set into the entities_closure vector
00175   entities_closure.assign(temp_entities_closure.begin(), temp_entities_closure.end());
00176 }
00177 
00178 } // namespace mesh
00179 } // namespace stk
00180 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends