|
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 #include <stk_mesh/base/Bucket.hpp> 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 00026 namespace stk { 00027 namespace mesh { 00028 00029 void set_field_relations( Entity & e_from , 00030 Entity & e_to , 00031 const unsigned ident ) 00032 { 00033 const std::vector<FieldRelation> & field_rels = 00034 e_from.bucket().mesh().mesh_meta_data().get_field_relations(); 00035 00036 for ( std::vector<FieldRelation>::const_iterator 00037 j = field_rels.begin() ; j != field_rels.end() ; ++j ) { 00038 00039 const FieldRelation & fr = *j ; 00040 00041 void ** const ptr = (void**) field_data( * fr.m_root , e_from ); 00042 00043 if ( ptr ) { 00044 00045 void * const src = field_data( * fr.m_target , e_to ); 00046 00047 const size_t number = 00048 field_data_size(*fr.m_root,e_from) / sizeof(void*); 00049 00050 const size_t offset = 00051 (*fr.m_function)( e_from.entity_rank() , 00052 e_to.entity_rank() , ident ); 00053 00054 if ( offset < number ) { 00055 ptr[ offset ] = src ; 00056 } 00057 } 00058 } 00059 } 00060 00061 00062 namespace { 00063 00064 void assert_valid_relation( const char method[] , 00065 const BulkData & mesh , 00066 const Entity & e_from , 00067 const Entity & e_to ) 00068 { 00069 const bool error_mesh_from = & mesh != & e_from.bucket().mesh(); 00070 const bool error_mesh_to = & mesh != & e_to.bucket().mesh(); 00071 const bool error_type = e_from.entity_rank() <= e_to.entity_rank(); 00072 const bool error_nil_from = EntityLogDeleted == e_from.log_query(); 00073 const bool error_nil_to = EntityLogDeleted == e_to.log_query(); 00074 00075 if ( error_mesh_from || error_mesh_to || error_type || 00076 error_nil_from || error_nil_to ) { 00077 std::ostringstream msg ; 00078 msg << method << "( from " ; 00079 print_entity_key( msg , mesh.mesh_meta_data(), e_from.key() ); 00080 if ( error_mesh_from ) { 00081 msg << " NOT MEMBER OF THIS MESH" ; 00082 } 00083 if ( error_nil_from ) { 00084 msg << " WAS DESTROYED" ; 00085 } 00086 msg << " , to " ; 00087 print_entity_key( msg , mesh.mesh_meta_data(), e_to.key() ); 00088 if ( error_mesh_to ) { 00089 msg << " NOT MEMBER OF THIS MESH" ; 00090 } 00091 if ( error_nil_to ) { 00092 msg << " WAS DESTROYED" ; 00093 } 00094 msg << " ) FAILED" ; 00095 if ( error_type ) { 00096 msg << " A relation must be from higher to lower ranking entity" ; 00097 } 00098 throw std::runtime_error( msg.str() ); 00099 } 00100 } 00101 00102 00103 void clear_field_relations( Entity & e_from , 00104 const unsigned type , 00105 const unsigned ident ) 00106 00107 { 00108 const std::vector<FieldRelation> & field_rels = 00109 e_from.bucket().mesh().mesh_meta_data().get_field_relations(); 00110 00111 for ( std::vector<FieldRelation>::const_iterator 00112 j = field_rels.begin() ; j != field_rels.end() ; ++j ) { 00113 00114 const FieldRelation & fr = *j ; 00115 00116 void ** const ptr = (void**) field_data( * fr.m_root , e_from ); 00117 00118 if ( ptr ) { 00119 00120 const size_t number = 00121 field_data_size(*fr.m_root,e_from) / sizeof(void*); 00122 00123 const size_t offset = 00124 (*fr.m_function)( e_from.entity_rank() , type , ident ); 00125 00126 if ( offset < number ) { 00127 ptr[ offset ] = NULL ; 00128 } 00129 } 00130 } 00131 } 00132 00133 } 00134 00135 //---------------------------------------------------------------------- 00136 00137 void BulkData::declare_relation( Entity & e_from , 00138 Entity & e_to , 00139 const unsigned local_id ) 00140 { 00141 static const char method[] = "stk::mesh::BulkData::declare_relation" ; 00142 00143 assert_ok_to_modify( method ); 00144 00145 assert_valid_relation( method , *this , e_from , e_to ); 00146 00147 m_entity_repo.declare_relation( e_from, e_to, local_id, m_sync_count); 00148 00149 00150 PartVector add , empty ; 00151 00152 // Deduce and set new part memberships: 00153 00154 induced_part_membership( e_from, empty, 00155 e_to.entity_rank(), local_id, add ); 00156 00157 internal_change_entity_parts( e_to , add , empty ); 00158 00159 set_field_relations( e_from , e_to , local_id ); 00160 } 00161 00162 //---------------------------------------------------------------------- 00163 00164 void BulkData::declare_relation( Entity & entity , 00165 const std::vector<Relation> & rel ) 00166 { 00167 static const char method[] = "stk::mesh::BulkData::declare_relation" ; 00168 00169 assert_ok_to_modify( method ); 00170 00171 const unsigned etype = entity.entity_rank(); 00172 00173 std::vector<Relation>::const_iterator i ; 00174 for ( i = rel.begin() ; i != rel.end() ; ++i ) { 00175 Entity & e = * i->entity(); 00176 const unsigned n = i->identifier(); 00177 if ( e.entity_rank() < etype ) { 00178 declare_relation( entity , e , n ); 00179 } 00180 else if ( etype < e.entity_rank() ) { 00181 declare_relation( e , entity , n ); 00182 } 00183 else { 00184 throw std::runtime_error( std::string("stk::mesh::BulkData::declare_relation FAILED: given entities of the same entity type") ); 00185 } 00186 } 00187 } 00188 00189 //---------------------------------------------------------------------- 00190 00191 void BulkData::destroy_relation( Entity & e_from , Entity & e_to ) 00192 { 00193 static const char method[]= "stk::mesh::BulkData::destroy_relation" ; 00194 00195 assert_ok_to_modify( method ); 00196 00197 assert_valid_relation( method , *this , e_from , e_to ); 00198 00199 00200 //------------------------------ 00201 // When removing a relationship may need to 00202 // remove part membership and set field relation pointer to NULL 00203 00204 PartVector del , keep ; 00205 00206 for ( PairIterRelation i = e_to.relations() ; i.first != i.second ; ++(i.first) ) { 00207 00208 if ( !( i.first->entity() == & e_from ) && 00209 ( e_to.entity_rank() < i.first->entity_rank() ) ) 00210 { 00211 induced_part_membership( * i.first->entity(), del, e_to.entity_rank(), 00212 i.first->identifier(), keep ); 00213 } 00214 } 00215 00216 for ( PairIterRelation i = e_from.relations() ; i.first != i.second ; ++(i.first) ) { 00217 if ( i.first->entity() == & e_to ) { 00218 00219 induced_part_membership( e_from, keep, e_to.entity_rank(), 00220 i.first->identifier(), del ); 00221 00222 clear_field_relations( e_from , e_to.entity_rank() , 00223 i.first->identifier() ); 00224 } 00225 } 00226 00227 //------------------------------ 00228 // 'keep' contains the parts deduced from kept relations 00229 // 'del' contains the parts deduced from deleted relations 00230 // that are not in 'keep' 00231 // Only remove these part memberships the entity is not shared. 00232 // If the entity is shared then wait until modificaton_end_synchronize. 00233 //------------------------------ 00234 00235 if ( ! del.empty() && (parallel_size() < 2 || e_to.sharing().empty()) ) { 00236 PartVector add ; 00237 internal_change_entity_parts( e_to , add , del ); 00238 } 00239 00240 //delete relations from the entities 00241 m_entity_repo.destroy_relation( e_from, e_to); 00242 00243 } 00244 00245 //---------------------------------------------------------------------- 00246 // Deduce propagation of part membership changes to a 'from' entity 00247 // to the related 'to' entities. There can be both additions and 00248 // removals. 00249 00250 void BulkData::internal_propagate_part_changes( 00251 Entity & entity , 00252 const PartVector & removed ) 00253 { 00254 const unsigned etype = entity.entity_rank(); 00255 00256 PairIterRelation rel = entity.relations(); 00257 00258 for ( ; ! rel.empty() ; ++rel ) { 00259 const unsigned rel_type = rel->entity_rank(); 00260 const unsigned rel_ident = rel->identifier(); 00261 00262 if ( rel_type < etype ) { // a 'to' entity 00263 00264 Entity & e_to = * rel->entity(); 00265 00266 PartVector to_del , to_add , empty ; 00267 00268 // Induce part membership from this relationship to 00269 // pick up any additions. 00270 induced_part_membership( entity, empty, 00271 rel_type, rel_ident, to_add ); 00272 00273 if ( ! removed.empty() ) { 00274 // Something was removed from the 'from' entity, 00275 // deduce what may have to be removed from the 'to' entity. 00276 00277 // Deduce parts for 'e_to' from all upward relations. 00278 // Any non-parallel part that I removed that is not deduced for 00279 // 'e_to' must be removed from 'e_to' 00280 00281 for ( PairIterRelation 00282 to_rel = e_to.relations(); ! to_rel.empty() ; ++to_rel ) { 00283 if ( e_to.entity_rank() < to_rel->entity_rank() && 00284 & entity != to_rel->entity() /* Already did this entity */ ) { 00285 // Relation from to_rel->entity() to e_to 00286 induced_part_membership( * to_rel->entity(), empty, 00287 e_to.entity_rank(), 00288 to_rel->identifier(), 00289 to_add ); 00290 } 00291 } 00292 00293 for ( PartVector::const_iterator 00294 j = removed.begin() ; j != removed.end() ; ++j ) { 00295 if ( ! contain( to_add , **j ) ) { 00296 induced_part_membership( **j, etype, rel_type, rel_ident, to_del ); 00297 } 00298 } 00299 } 00300 00301 if ( parallel_size() < 2 || e_to.sharing().empty() ) { 00302 // Entirely local, ok to remove memberships now 00303 internal_change_entity_parts( e_to , to_add , to_del ); 00304 } 00305 else { 00306 // Shared, do not remove memberships now. 00307 // Wait until modification_end. 00308 internal_change_entity_parts( e_to , to_add , empty ); 00309 } 00310 00311 set_field_relations( entity, e_to, rel_ident ); 00312 } 00313 else if ( etype < rel_type ) { // a 'from' entity 00314 Entity & e_from = * rel->entity(); 00315 00316 set_field_relations( e_from, entity, rel_ident ); 00317 } 00318 } 00319 } 00320 00321 //---------------------------------------------------------------------- 00322 //---------------------------------------------------------------------- 00323 00324 } // namespace mesh 00325 } // namespace stk 00326