|
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 00013 #include <stdexcept> 00014 #include <iostream> 00015 #include <sstream> 00016 #include <algorithm> 00017 00018 #include <stk_util/parallel/ParallelComm.hpp> 00019 #include <stk_util/parallel/ParallelReduce.hpp> 00020 00021 #include <stk_mesh/base/BulkData.hpp> 00022 #include <stk_mesh/base/MetaData.hpp> 00023 #include <stk_mesh/base/Comm.hpp> 00024 #include <stk_mesh/base/FieldData.hpp> 00025 #include <stk_mesh/base/Trace.hpp> 00026 00027 namespace stk_classic { 00028 namespace mesh { 00029 00030 void set_field_relations( Entity & e_from , 00031 Entity & e_to , 00032 const unsigned ident ) 00033 { 00034 const std::vector<FieldRelation> & field_rels = 00035 MetaData::get(e_from).get_field_relations(); 00036 00037 for ( std::vector<FieldRelation>::const_iterator 00038 j = field_rels.begin() ; j != field_rels.end() ; ++j ) { 00039 00040 const FieldRelation & fr = *j ; 00041 00042 void ** const ptr = (void**) field_data( * fr.m_root , e_from ); 00043 00044 if ( ptr ) { 00045 00046 void * const src = field_data( * fr.m_target , e_to ); 00047 00048 const size_t number = 00049 field_data_size(*fr.m_root,e_from) / sizeof(void*); 00050 00051 const size_t offset = 00052 (*fr.m_function)( e_from.entity_rank() , 00053 e_to.entity_rank() , ident ); 00054 00055 if ( offset < number ) { 00056 ptr[ offset ] = src ; 00057 } 00058 } 00059 } 00060 } 00061 00062 namespace { 00063 00064 void clear_field_relations( Entity & e_from , 00065 const unsigned type , 00066 const unsigned ident ) 00067 { 00068 const std::vector<FieldRelation> & field_rels = 00069 MetaData::get(e_from).get_field_relations(); 00070 00071 for ( std::vector<FieldRelation>::const_iterator 00072 j = field_rels.begin() ; j != field_rels.end() ; ++j ) { 00073 00074 const FieldRelation & fr = *j ; 00075 00076 void ** const ptr = (void**) field_data( * fr.m_root , e_from ); 00077 00078 if ( ptr ) { 00079 00080 const size_t number = 00081 field_data_size(*fr.m_root,e_from) / sizeof(void*); 00082 00083 const size_t offset = 00084 (*fr.m_function)( e_from.entity_rank() , type , ident ); 00085 00086 if ( offset < number ) { 00087 ptr[ offset ] = NULL ; 00088 } 00089 } 00090 } 00091 } 00092 00093 } // empty namespace 00094 00095 //---------------------------------------------------------------------- 00096 00097 void BulkData::require_valid_relation( const char action[] , 00098 const BulkData & mesh , 00099 const Entity & e_from , 00100 const Entity & e_to ) 00101 { 00102 const bool error_mesh_from = & mesh != & BulkData::get(e_from); 00103 const bool error_mesh_to = & mesh != & BulkData::get(e_to); 00104 const bool error_type = e_from.entity_rank() <= e_to.entity_rank(); 00105 const bool error_nil_from = EntityLogDeleted == e_from.log_query(); 00106 const bool error_nil_to = EntityLogDeleted == e_to.log_query(); 00107 00108 if ( error_mesh_from || error_mesh_to || error_type || 00109 error_nil_from || error_nil_to ) { 00110 std::ostringstream msg ; 00111 00112 msg << "Could not " << action << " relation from entity " 00113 << print_entity_key(e_from) << " to entity " 00114 << print_entity_key(e_to) << "\n"; 00115 00116 ThrowErrorMsgIf( error_mesh_from || error_mesh_to, 00117 msg.str() << (error_mesh_from ? "e_from" : "e_to" ) << 00118 " not member of this mesh"); 00119 ThrowErrorMsgIf( error_nil_from || error_nil_to, 00120 msg.str() << (error_mesh_from ? "e_from" : "e_to" ) << 00121 " was destroyed"); 00122 ThrowErrorMsgIf( error_type, msg.str() << 00123 "A relation must be from higher to lower ranking entity"); 00124 } 00125 } 00126 00127 //---------------------------------------------------------------------- 00128 00129 void BulkData::declare_relation( Entity & e_from , 00130 Entity & e_to , 00131 const RelationIdentifier local_id ) 00132 { 00133 TraceIfWatching("stk_classic::mesh::BulkData::declare_relation", LOG_ENTITY, e_from.key()); 00134 TraceIfWatchingDec("stk_classic::mesh::BulkData::declare_relation", LOG_ENTITY, e_to.key(), 1); 00135 DiagIfWatching(LOG_ENTITY, e_from.key(), 00136 "from: " << e_from << "; " << 00137 "to: " << e_to << "; " << 00138 "id: " << local_id); 00139 DiagIfWatching(LOG_ENTITY, e_to.key(), 00140 "from: " << e_from << "; " << 00141 "to: " << e_to << "; " << 00142 "id: " << local_id); 00143 00144 require_ok_to_modify(); 00145 00146 require_valid_relation( "declare" , *this , e_from , e_to ); 00147 00148 // TODO: Don't throw if exact relation already exists, that should be a no-op. 00149 // Should be an exact match if relation of local_id already exists (e_to should be the same). 00150 m_entity_repo.declare_relation( e_from, e_to, local_id, m_sync_count); 00151 00152 OrdinalVector add , empty ; 00153 00154 // Deduce and set new part memberships: 00155 00156 induced_part_membership( e_from, empty, e_to.entity_rank(), local_id, add ); 00157 00158 internal_change_entity_parts( e_to , add , empty ); 00159 00160 set_field_relations( e_from , e_to , local_id ); 00161 } 00162 00163 //---------------------------------------------------------------------- 00164 00165 void BulkData::declare_relation( Entity & entity , 00166 const std::vector<Relation> & rel ) 00167 { 00168 require_ok_to_modify(); 00169 00170 const unsigned erank = entity.entity_rank(); 00171 00172 std::vector<Relation>::const_iterator i ; 00173 for ( i = rel.begin() ; i != rel.end() ; ++i ) { 00174 Entity & e = * i->entity(); 00175 const unsigned n = i->identifier(); 00176 if ( e.entity_rank() < erank ) { 00177 declare_relation( entity , e , n ); 00178 } 00179 else if ( erank < e.entity_rank() ) { 00180 declare_relation( e , entity , n ); 00181 } 00182 else { 00183 ThrowErrorMsg("Given entities of the same entity rank. entity is " << 00184 print_entity_key(entity)); 00185 } 00186 } 00187 } 00188 00189 //---------------------------------------------------------------------- 00190 00191 bool BulkData::destroy_relation( Entity & e_from , 00192 Entity & e_to, 00193 const RelationIdentifier local_id ) 00194 { 00195 TraceIfWatching("stk_classic::mesh::BulkData::destroy_relation", LOG_ENTITY, e_from.key()); 00196 TraceIfWatchingDec("stk_classic::mesh::BulkData::destroy_relation", LOG_ENTITY, e_to.key(), 1); 00197 DiagIfWatching(LOG_ENTITY, e_from.key(), 00198 "from: " << e_from << "; " << 00199 "to: " << e_to << "; " << 00200 "id: " << local_id); 00201 DiagIfWatching(LOG_ENTITY, e_to.key(), 00202 "from: " << e_from << "; " << 00203 "to: " << e_to << "; " << 00204 "id: " << local_id); 00205 00206 require_ok_to_modify(); 00207 00208 require_valid_relation( "destroy" , *this , e_from , e_to ); 00209 00210 //------------------------------ 00211 // When removing a relationship may need to 00212 // remove part membership and set field relation pointer to NULL 00213 00214 if ( parallel_size() < 2 || m_entity_comm_map.sharing(e_to.key()).empty() ) { 00215 00216 //------------------------------ 00217 // 'keep' contains the parts deduced from kept relations 00218 // 'del' contains the parts deduced from deleted relations 00219 // that are not in 'keep' 00220 // Only remove these part memberships the entity is not shared. 00221 // If the entity is shared then wait until modificaton_end_synchronize. 00222 //------------------------------ 00223 00224 OrdinalVector del, keep, empty; 00225 00226 // For all relations that are *not* being deleted, add induced parts for 00227 // these relations to the 'keep' vector 00228 for ( PairIterRelation i = e_to.relations(); !i.empty(); ++i ) { 00229 if (e_to.entity_rank() < i->entity_rank()) { // Need to look at back rels only 00230 if ( !( i->entity() == & e_from && i->identifier() == local_id ) ) { 00231 induced_part_membership( * i->entity(), empty, e_to.entity_rank(), 00232 i->identifier(), keep, 00233 false /*Do not look at supersets*/); 00234 } 00235 } 00236 } 00237 00238 // Find the relation this is being deleted and add the parts that are 00239 // induced from that relation (and that are not in 'keep') to 'del' 00240 for ( PairIterRelation i = e_from.relations() ; !i.empty() ; ++i ) { 00241 if ( i->entity() == & e_to && i->identifier() == local_id ) { 00242 induced_part_membership( e_from, keep, e_to.entity_rank(), 00243 i->identifier(), del, 00244 false /*Do not look at supersets*/); 00245 clear_field_relations( e_from , e_to.entity_rank() , 00246 i->identifier() ); 00247 break; // at most 1 relation can match our specification 00248 } 00249 } 00250 00251 if ( !del.empty() ) { 00252 internal_change_entity_parts( e_to , empty , del ); 00253 } 00254 } 00255 else { 00256 // Just clear the field, part membership will be handled by modification end 00257 for ( PairIterRelation i = e_from.relations() ; !i.empty() ; ++i ) { 00258 if ( i->entity() == & e_to && i->identifier() == local_id ) { 00259 clear_field_relations( e_from , e_to.entity_rank() , 00260 i->identifier() ); 00261 break; // at most 1 relation can match our specification 00262 } 00263 } 00264 } 00265 00266 //delete relations from the entities 00267 return m_entity_repo.destroy_relation( e_from, e_to, local_id); 00268 } 00269 00270 //---------------------------------------------------------------------- 00271 // Deduce propagation of part membership changes to a 'from' entity 00272 // to the related 'to' entities. There can be both additions and 00273 // removals. 00274 00275 void BulkData::internal_propagate_part_changes( 00276 Entity & entity , 00277 const PartVector & removed ) 00278 { 00279 TraceIfWatching("stk_classic::mesh::BulkData::internal_propagate_part_changes", 00280 LOG_ENTITY, 00281 entity.key()); 00282 DiagIfWatching(LOG_ENTITY, entity.key(), "entity state: " << entity); 00283 DiagIfWatching(LOG_ENTITY, entity.key(), "Removed: " << removed); 00284 00285 const unsigned etype = entity.entity_rank(); 00286 00287 PairIterRelation rel = entity.relations(); 00288 00289 OrdinalVector to_del , to_add , empty ; 00290 00291 for ( ; ! rel.empty() ; ++rel ) { 00292 const unsigned rel_type = rel->entity_rank(); 00293 const unsigned rel_ident = rel->identifier(); 00294 00295 if ( rel_type < etype ) { // a 'to' entity 00296 00297 Entity & e_to = * rel->entity(); 00298 00299 to_del.clear(); 00300 to_add.clear(); 00301 empty.clear(); 00302 00303 // Induce part membership from this relationship to 00304 // pick up any additions. 00305 induced_part_membership( entity, empty, 00306 rel_type, rel_ident, to_add ); 00307 00308 if ( ! removed.empty() ) { 00309 // Something was removed from the 'from' entity, 00310 // deduce what may have to be removed from the 'to' entity. 00311 00312 // Deduce parts for 'e_to' from all upward relations. 00313 // Any non-parallel part that I removed that is not deduced for 00314 // 'e_to' must be removed from 'e_to' 00315 00316 for ( PairIterRelation 00317 to_rel = e_to.relations(); ! to_rel.empty() ; ++to_rel ) { 00318 if ( e_to.entity_rank() < to_rel->entity_rank() && 00319 & entity != to_rel->entity() /* Already did this entity */ ) { 00320 // Relation from to_rel->entity() to e_to 00321 induced_part_membership( * to_rel->entity(), empty, 00322 e_to.entity_rank(), 00323 to_rel->identifier(), 00324 to_add ); 00325 } 00326 } 00327 00328 OrdinalVector::const_iterator to_add_begin = to_add.begin(), 00329 to_add_end = to_add.end(); 00330 00331 for ( PartVector::const_iterator 00332 j = removed.begin() ; j != removed.end() ; ++j ) { 00333 if ( ! contains_ordinal( to_add_begin, to_add_end , (*j)->mesh_meta_data_ordinal() ) ) { 00334 induced_part_membership( **j, etype, rel_type, rel_ident, to_del ); 00335 } 00336 } 00337 } 00338 00339 if ( parallel_size() < 2 || m_entity_comm_map.sharing(e_to.key()).empty() ) { 00340 // Entirely local, ok to remove memberships now 00341 internal_change_entity_parts( e_to , to_add , to_del ); 00342 } 00343 else { 00344 // Shared, do not remove memberships now. 00345 // Wait until modification_end. 00346 internal_change_entity_parts( e_to , to_add , empty ); 00347 } 00348 00349 set_field_relations( entity, e_to, rel_ident ); 00350 } 00351 else if ( etype < rel_type ) { // a 'from' entity 00352 Entity & e_from = * rel->entity(); 00353 00354 set_field_relations( e_from, entity, rel_ident ); 00355 } 00356 } 00357 } 00358 00359 void BulkData::internal_propagate_part_changes( 00360 Entity & entity , 00361 const OrdinalVector & removed ) 00362 { 00363 TraceIfWatching("stk_classic::mesh::BulkData::internal_propagate_part_changes", 00364 LOG_ENTITY, 00365 entity.key()); 00366 DiagIfWatching(LOG_ENTITY, entity.key(), "entity state: " << entity); 00367 DiagIfWatching(LOG_ENTITY, entity.key(), "Removed: " << removed); 00368 00369 const unsigned etype = entity.entity_rank(); 00370 00371 PairIterRelation rel = entity.relations(); 00372 00373 OrdinalVector to_del , to_add , empty ; 00374 00375 const PartVector& all_parts = m_mesh_meta_data.get_parts(); 00376 00377 for ( ; ! rel.empty() ; ++rel ) { 00378 const unsigned rel_type = rel->entity_rank(); 00379 const unsigned rel_ident = rel->identifier(); 00380 00381 if ( rel_type < etype ) { // a 'to' entity 00382 00383 Entity & e_to = * rel->entity(); 00384 00385 to_del.clear(); 00386 to_add.clear(); 00387 empty.clear(); 00388 00389 // Induce part membership from this relationship to 00390 // pick up any additions. 00391 induced_part_membership( entity, empty, 00392 rel_type, rel_ident, to_add ); 00393 00394 if ( ! removed.empty() ) { 00395 // Something was removed from the 'from' entity, 00396 // deduce what may have to be removed from the 'to' entity. 00397 00398 // Deduce parts for 'e_to' from all upward relations. 00399 // Any non-parallel part that I removed that is not deduced for 00400 // 'e_to' must be removed from 'e_to' 00401 00402 for ( PairIterRelation 00403 to_rel = e_to.relations(); ! to_rel.empty() ; ++to_rel ) { 00404 if ( e_to.entity_rank() < to_rel->entity_rank() && 00405 & entity != to_rel->entity() /* Already did this entity */ ) { 00406 // Relation from to_rel->entity() to e_to 00407 induced_part_membership( * to_rel->entity(), empty, 00408 e_to.entity_rank(), 00409 to_rel->identifier(), 00410 to_add ); 00411 } 00412 } 00413 00414 OrdinalVector::const_iterator to_add_begin = to_add.begin(), 00415 to_add_end = to_add.end(); 00416 00417 for ( OrdinalVector::const_iterator 00418 j = removed.begin() ; j != removed.end() ; ++j ) { 00419 if ( ! contains_ordinal( to_add_begin, to_add_end , *j ) ) { 00420 induced_part_membership( *all_parts[*j], etype, rel_type, rel_ident, to_del ); 00421 } 00422 } 00423 } 00424 00425 if ( parallel_size() < 2 || m_entity_comm_map.sharing(e_to.key()).empty() ) { 00426 // Entirely local, ok to remove memberships now 00427 internal_change_entity_parts( e_to , to_add , to_del ); 00428 } 00429 else { 00430 // Shared, do not remove memberships now. 00431 // Wait until modification_end. 00432 internal_change_entity_parts( e_to , to_add , empty ); 00433 } 00434 00435 set_field_relations( entity, e_to, rel_ident ); 00436 } 00437 else if ( etype < rel_type ) { // a 'from' entity 00438 Entity & e_from = * rel->entity(); 00439 00440 set_field_relations( e_from, entity, rel_ident ); 00441 } 00442 } 00443 } 00444 00445 //---------------------------------------------------------------------- 00446 //---------------------------------------------------------------------- 00447 00448 } // namespace mesh 00449 } // namespace stk_classic 00450