|
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 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_classic { 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_classic::mesh::find_closure( const BulkData & bulk, ... ) bulk is not synchronized"; 00144 } 00145 else if ( 0 < non_used_entities) { 00146 msg << "stk_classic::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_classic 00180