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_mesh/base/BulkModification.hpp>
00014 
00015 #include <stk_mesh/base/BulkData.hpp>
00016 #include <stk_mesh/base/Entity.hpp>
00017 #include <stk_util/parallel/ParallelComm.hpp>
00018 
00019 
00020 namespace stk {
00021 namespace mesh {
00022 
00023 typedef std::vector<Entity *> EntityVector;
00024 typedef std::set<Entity *, EntityLess> EntitySet;
00025 typedef std::set<EntityProc , EntityLess> EntityProcSet;
00026 
00027 namespace {
00028 
00029 void construct_transitive_closure( EntitySet & closure , Entity & entry )
00030 {
00031 
00032   std::pair< EntitySet::const_iterator , bool >
00033     result = closure.insert( & entry );
00034 
00035   // A new insertion, must also insert the closure
00036   if ( result.second ) {
00037 
00038     const unsigned etype = entry.entity_type();
00039     PairIterRelation irel  = entry.relations();
00040 
00041     for ( ; irel.first != irel.second ; ++irel.first ) {
00042       // insert entities with relations of lower rank into the closure
00043       if ( irel.first->entity_rank() < etype ) {
00044         Entity * tmp = irel.first->entity();
00045         construct_transitive_closure( closure , *tmp );
00046       }
00047     }
00048   }
00049 }
00050 
00051 void find_local_closure ( EntitySet & closure, const EntityVector & entities)
00052 {
00053   for (EntityVector::const_iterator i = entities.begin();
00054       i != entities.end(); ++i)
00055   {
00056     construct_transitive_closure(closure, **i);
00057   }
00058 }
00059 
00060 void construct_communication_set( const BulkData & bulk, const EntitySet & closure, EntityProcSet & communication_set)
00061 {
00062   if (bulk.parallel_size() < 2) return;
00063 
00064   for ( EntitySet::const_iterator
00065         i = closure.begin(); i != closure.end(); ++i) {
00066 
00067     Entity & entity = **i;
00068 
00069     const bool owned = bulk.parallel_rank() == entity.owner_rank();
00070 
00071     // Add sharing processes and ghost-send processes to communication_set
00072 
00073     for ( PairIterEntityComm ec = entity.comm(); ! ec.empty() ; ++ec ) {
00074       if ( owned || ec->ghost_id == 0 ) {
00075         EntityProc tmp( & entity , ec->proc );
00076         communication_set.insert( tmp );
00077       }
00078     }
00079   }
00080 }
00081 
00082 size_t count_non_used_entities( const BulkData & bulk, const EntityVector & entities)
00083 {
00084 
00085   size_t non_used_entities = 0;
00086 
00087   const Part & locally_used_part = bulk.mesh_meta_data().locally_used_part();
00088 
00089   //Check that entities are only in the locally_used part
00090   for (EntityVector::const_iterator i = entities.begin();
00091       i != entities.end(); ++i)
00092   {
00093     const Bucket & b = (**i).bucket();
00094     if ( ! has_superset(b, locally_used_part)) {
00095       ++non_used_entities;
00096     }
00097   }
00098 
00099   return non_used_entities;
00100 
00101 }
00102 
00103 }
00104 
00105 
00106 
00107 void find_closure( const BulkData & bulk,
00108     const std::vector< Entity *> & entities,
00109     std::vector< Entity *> & entities_closure)
00110 {
00111 
00112   entities_closure.clear();
00113 
00114 
00115   EntityProcSet send_list;
00116   EntitySet     temp_entities_closure;
00117 
00118   const bool bulk_not_synchronized = bulk.synchronized_state() != BulkData::SYNCHRONIZED;
00119   const size_t non_used_entities = bulk_not_synchronized ? 0 : count_non_used_entities(bulk, entities);
00120 
00121   const bool local_bad_input = bulk_not_synchronized || (0 < non_used_entities);
00122 
00123   //Can skip if error on input
00124   if ( !local_bad_input) {
00125 
00126     find_local_closure(temp_entities_closure, entities);
00127 
00128     construct_communication_set(bulk, temp_entities_closure, send_list);
00129   }
00130 
00131 
00132   CommAll all( bulk.parallel() );
00133 
00134   //pack send_list for sizing
00135   for ( EntityProcSet::const_iterator
00136       ep = send_list.begin() ; ep != send_list.end() ; ++ep ) {
00137     all.send_buffer( ep->second).pack<EntityKey>(ep->first->key());
00138   }
00139 
00140 
00141   const bool global_bad_input = all.allocate_buffers( bulk.parallel_size() / 4 , false, local_bad_input );
00142 
00143   if (global_bad_input) {
00144 
00145     std::ostringstream msg;
00146     //parallel consisent throw
00147     if (bulk_not_synchronized) {
00148       msg << "stk::mesh::find_closure( const BulkData & bulk, ... ) bulk is not synchronized";
00149     }
00150     else if ( 0 < non_used_entities) {
00151       msg << "stk::mesh::find_closure( const BulkData & bulk, std::vector<Entity *> entities, ... ) \n"
00152           << "entities contains " << non_used_entities << " non locally used entities \n";
00153     }
00154 
00155     throw std::runtime_error(msg.str());
00156   }
00157 
00158 
00159   //pack send_list
00160   for ( EntityProcSet::const_iterator
00161       ep = send_list.begin() ; ep != send_list.end() ; ++ep ) {
00162     all.send_buffer( ep->second).pack<EntityKey>(ep->first->key());
00163   }
00164 
00165 
00166   all.communicate();
00167 
00168   //unpack the send_list into the temp entities closure set
00169   for ( unsigned p = 0 ; p < bulk.parallel_size() ; ++p ) {
00170     CommBuffer & buf = all.recv_buffer( p );
00171     EntityKey k ;
00172     while ( buf.remaining() ) {
00173       buf.unpack<EntityKey>( k );
00174       Entity * e = bulk.get_entity(k);
00175       temp_entities_closure.insert(e);
00176     }
00177   }
00178 
00179   //copy the set into the entities_closure vector
00180   entities_closure.assign(temp_entities_closure.begin(), temp_entities_closure.end());
00181 }
00182 
00183 } // namespace mesh
00184 } // namespace stk
00185 

Generated on Tue Jul 13 09:27:31 2010 for Sierra Toolkit by  doxygen 1.4.7