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 
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 {
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::mesh::BulkData::declare_relation", LOG_ENTITY, e_from.key());
00134   TraceIfWatchingDec("stk::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   PartVector 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::mesh::BulkData::destroy_relation", LOG_ENTITY, e_from.key());
00196   TraceIfWatchingDec("stk::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 || e_to.sharing().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     PartVector 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();
00229           !i.empty() && e_to.entity_rank() < i->entity_rank();
00230           ++i ) {
00231       if ( !( i->entity() == & e_from && i->identifier() == local_id ) ) {
00232         induced_part_membership( * i->entity(), empty, e_to.entity_rank(),
00233                                  i->identifier(), keep );
00234       }
00235     }
00236 
00237     // Find the relation this is being deleted and add the parts that are
00238     // induced from that relation (and that are not in 'keep') to 'del'
00239     for ( PairIterRelation i = e_from.relations() ; !i.empty() ; ++i ) {
00240       if ( i->entity() == & e_to && i->identifier() == local_id ) {
00241         induced_part_membership( e_from, keep, e_to.entity_rank(),
00242                                  i->identifier(), del );
00243         clear_field_relations( e_from , e_to.entity_rank() ,
00244                                i->identifier() );
00245         break; // at most 1 relation can match our specification
00246       }
00247     }
00248 
00249     if ( !del.empty() ) {
00250       internal_change_entity_parts( e_to , empty , del );
00251     }
00252   }
00253   else {
00254     // Just clear the field, part membership will be handled by modification end
00255     for ( PairIterRelation i = e_from.relations() ; !i.empty() ; ++i ) {
00256       if ( i->entity() == & e_to && i->identifier() == local_id ) {
00257         clear_field_relations( e_from , e_to.entity_rank() ,
00258                                i->identifier() );
00259         break; // at most 1 relation can match our specification
00260       }
00261     }
00262   }
00263 
00264   //delete relations from the entities
00265   return m_entity_repo.destroy_relation( e_from, e_to, local_id);
00266 }
00267 
00268 //----------------------------------------------------------------------
00269 // Deduce propagation of part membership changes to a 'from' entity
00270 // to the related 'to' entities.  There can be both additions and
00271 // removals.
00272 
00273 void BulkData::internal_propagate_part_changes(
00274   Entity           & entity ,
00275   const PartVector & removed )
00276 {
00277   TraceIfWatching("stk::mesh::BulkData::internal_propagate_part_changes",
00278                   LOG_ENTITY,
00279                   entity.key());
00280   DiagIfWatching(LOG_ENTITY, entity.key(), "entity state: " << entity);
00281   DiagIfWatching(LOG_ENTITY, entity.key(), "Removed: " << removed);
00282 
00283   const unsigned etype = entity.entity_rank();
00284 
00285   PairIterRelation rel = entity.relations();
00286 
00287   for ( ; ! rel.empty() ; ++rel ) {
00288     const unsigned rel_type  = rel->entity_rank();
00289     const unsigned rel_ident = rel->identifier();
00290 
00291     if ( rel_type < etype ) { // a 'to' entity
00292 
00293       Entity & e_to = * rel->entity();
00294 
00295       PartVector to_del , to_add , empty ;
00296 
00297       // Induce part membership from this relationship to
00298       // pick up any additions.
00299       induced_part_membership( entity, empty,
00300                                rel_type, rel_ident, to_add );
00301 
00302       if ( ! removed.empty() ) {
00303         // Something was removed from the 'from' entity,
00304         // deduce what may have to be removed from the 'to' entity.
00305 
00306         // Deduce parts for 'e_to' from all upward relations.
00307         // Any non-parallel part that I removed that is not deduced for
00308         // 'e_to' must be removed from 'e_to'
00309 
00310         for ( PairIterRelation
00311               to_rel = e_to.relations(); ! to_rel.empty() ; ++to_rel ) {
00312           if ( e_to.entity_rank() < to_rel->entity_rank() &&
00313                & entity != to_rel->entity() /* Already did this entity */ ) {
00314             // Relation from to_rel->entity() to e_to
00315             induced_part_membership( * to_rel->entity(), empty,
00316                                      e_to.entity_rank(),
00317                                      to_rel->identifier(),
00318                                      to_add );
00319           }
00320         }
00321 
00322         for ( PartVector::const_iterator
00323               j = removed.begin() ; j != removed.end() ; ++j ) {
00324           if ( ! contain( to_add , **j ) ) {
00325             induced_part_membership( **j, etype, rel_type, rel_ident, to_del );
00326           }
00327         }
00328       }
00329 
00330       if ( parallel_size() < 2 || e_to.sharing().empty() ) {
00331         // Entirely local, ok to remove memberships now
00332         internal_change_entity_parts( e_to , to_add , to_del );
00333       }
00334       else {
00335         // Shared, do not remove memberships now.
00336         // Wait until modification_end.
00337         internal_change_entity_parts( e_to , to_add , empty );
00338       }
00339 
00340       set_field_relations( entity, e_to, rel_ident );
00341     }
00342     else if ( etype < rel_type ) { // a 'from' entity
00343       Entity & e_from = * rel->entity();
00344 
00345       set_field_relations( e_from, entity, rel_ident );
00346     }
00347   }
00348 }
00349 
00350 //----------------------------------------------------------------------
00351 //----------------------------------------------------------------------
00352 
00353 } // namespace mesh
00354 } // namespace stk
00355 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends