Sierra Toolkit Version of the Day
BulkDataRelation.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 
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends