Sierra Toolkit Version of the Day
Relation.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 
00009 #include <stdexcept>
00010 #include <iostream>
00011 #include <sstream>
00012 #include <algorithm>
00013 
00014 #include <stk_mesh/base/MetaData.hpp>
00015 #include <stk_mesh/base/BulkData.hpp>
00016 #include <stk_mesh/base/Entity.hpp>
00017 #include <stk_mesh/base/Bucket.hpp>
00018 #include <stk_mesh/base/Relation.hpp>
00019 #include <stk_mesh/base/FieldData.hpp>
00020 
00021 namespace stk {
00022 namespace mesh {
00023 
00024 //----------------------------------------------------------------------
00025 
00026 std::ostream &
00027 operator << ( std::ostream & s , const Relation & rel )
00028 {
00029   Entity * const e = rel.entity();
00030 
00031   if ( e ) {
00032     const MetaData & meta_data = MetaData::get(*e);
00033     s << "[" << rel.identifier() << "]->" ;
00034     print_entity_key( s , meta_data , e->key() );
00035   }
00036   else {
00037     s << "[" << rel.identifier() << "]->" << rel.entity_rank();
00038   }
00039 
00040   return s ;
00041 }
00042 
00043 //----------------------------------------------------------------------
00044 
00045 Relation::Relation( Entity & entity , RelationIdentifier identifier )
00046   : m_raw_relation( Relation::raw_relation_id( entity.entity_rank() , identifier ) ),
00047     m_target_entity( & entity )
00048 {
00049 #ifdef SIERRA_MIGRATION
00050   setRelationType(INVALID);
00051 #endif
00052 }
00053 
00054 bool Relation::operator < ( const Relation & rhs ) const
00055 {
00056   bool result = false;
00057 
00058 #ifdef SIERRA_MIGRATION
00059   if (entity_rank() != rhs.entity_rank()) {
00060     result = entity_rank() < rhs.entity_rank();
00061   }
00062   else if (getRelationType() != rhs.getRelationType()) {
00063     result = getRelationType() < rhs.getRelationType();
00064   }
00065   else if (identifier() != rhs.identifier()) {
00066     result = identifier() < rhs.identifier();
00067   }
00068 #else
00069   if ( m_raw_relation.value != rhs.m_raw_relation.value ) {
00070     result = m_raw_relation.value < rhs.m_raw_relation.value ;
00071   }
00072 #endif
00073   else {
00074     const EntityKey lhs_key = m_target_entity     ? m_target_entity->key()     : EntityKey();
00075     const EntityKey rhs_key = rhs.m_target_entity ? rhs.m_target_entity->key() : EntityKey();
00076     result = lhs_key < rhs_key ;
00077   }
00078   return result ;
00079 }
00080 
00081 //----------------------------------------------------------------------
00082 
00083 #ifdef SIERRA_MIGRATION
00084 
00085 Relation::Relation(Entity *obj, const unsigned relation_type, const unsigned ordinal, const unsigned orient)
00086   :
00087   m_raw_relation( Relation::raw_relation_id( obj->entity_rank(), ordinal )),
00088   m_attribute( (relation_type << fmwk_orientation_digits) | orient ),
00089   m_target_entity(obj)
00090 {
00091   ThrowAssertMsg( orient <= fmwk_orientation_mask,
00092                   "orientation " << orient << " exceeds maximum allowed value");
00093 }
00094 
00095 void Relation::setMeshObj(Entity *object)
00096 {
00097   if (object != NULL) {
00098     m_raw_relation = Relation::raw_relation_id( object->entity_rank(), identifier() );
00099   }
00100   m_target_entity = object;
00101 }
00102 
00103 #endif
00104 
00105 namespace {
00106 
00107 void get_entities_through_relations(
00108   PairIterRelation rel ,
00109   const std::vector<Entity*>::const_iterator i_beg ,
00110   const std::vector<Entity*>::const_iterator i_end ,
00111   std::vector<Entity*> & entities_related )
00112 {
00113   for ( ; rel.first != rel.second ; ++rel.first ) {
00114 
00115     // Do all input entities have a relation to this entity ?
00116 
00117     Entity * const e = rel.first->entity();
00118 
00119     std::vector<Entity*>::const_iterator i = i_beg ;
00120 
00121     for ( ; i != i_end ; ++i ) {
00122       PairIterRelation r = (*i)->relations();
00123       while ( r.first != r.second && e != r.first->entity() ) {
00124         ++r.first ;
00125       }
00126       if ( r.first == r.second ) { break ; }
00127     }
00128 
00129     if ( i == i_end ) {
00130       entities_related.push_back( e );
00131     }
00132   }
00133 }
00134 
00135 inline
00136 void insert_part_and_supersets(OrdinalVector& induced_parts,
00137                                Part& part,
00138                                bool include_supersets)
00139 {
00140   insert_ordinal( induced_parts , part.mesh_meta_data_ordinal() );
00141 
00142   // In order to preserve superset/subset consistency we should add supersets of
00143   // induced parts to the induced part lists. Unfortunately, this opens up an ambiguity
00144   // where, when a relation is removed, we cannot know if an unranked superset
00145   // part should be removed.
00146   if (include_supersets) {
00147     const PartVector & supersets = part.supersets();
00148     for (PartVector::const_iterator itr = supersets.begin(), end = supersets.end(); itr != end; ++itr) {
00149       insert_ordinal( induced_parts, (*itr)->mesh_meta_data_ordinal() );
00150     }
00151   }
00152 }
00153 
00154 }
00155 
00156 void get_entities_through_relations(
00157   const std::vector<Entity*> & entities ,
00158         std::vector<Entity*> & entities_related )
00159 {
00160   entities_related.clear();
00161 
00162   if ( ! entities.empty() ) {
00163           std::vector<Entity*>::const_iterator i = entities.begin();
00164     const std::vector<Entity*>::const_iterator j = entities.end();
00165 
00166     PairIterRelation rel = (*i)->relations(); ++i ;
00167 
00168     get_entities_through_relations( rel , i , j , entities_related );
00169   }
00170 }
00171 
00172 void get_entities_through_relations(
00173   const std::vector<Entity*> & entities ,
00174         unsigned               entities_related_rank ,
00175         std::vector<Entity*> & entities_related )
00176 {
00177   entities_related.clear();
00178 
00179   if ( ! entities.empty() ) {
00180           std::vector<Entity*>::const_iterator i = entities.begin();
00181     const std::vector<Entity*>::const_iterator j = entities.end();
00182 
00183     PairIterRelation rel = (*i)->relations( entities_related_rank ); ++i ;
00184 
00185     get_entities_through_relations( rel , i , j , entities_related );
00186   }
00187 }
00188 
00189 //----------------------------------------------------------------------
00190 
00194 bool membership_is_induced( const Part & part , unsigned entity_rank )
00195 {
00196   const MetaData & meta = MetaData::get(part);
00197 
00198   const bool induced_by_type =
00199      entity_rank < part.primary_entity_rank() &&
00200                    part.primary_entity_rank() < meta.entity_rank_count() ;
00201 
00202   const bool induced_by_stencil =
00203     ! part.relations().empty() &&
00204       part.relations().begin()->m_target == & part ;
00205 
00206   return induced_by_type || induced_by_stencil ;
00207 }
00208 
00209 //----------------------------------------------------------------------
00210 
00211 void induced_part_membership( Part & part ,
00212                               unsigned entity_rank_from ,
00213                               unsigned entity_rank_to ,
00214                               RelationIdentifier relation_identifier ,
00215                               OrdinalVector & induced_parts,
00216                               bool include_supersets)
00217 {
00218   if ( entity_rank_to < entity_rank_from &&
00219        part.primary_entity_rank() == entity_rank_from ) {
00220 
00221     // Direct relationship:
00222 
00223     insert_part_and_supersets( induced_parts , part, include_supersets );
00224 
00225     // Stencil relationship where 'part' is the root:
00226     // The 'target' should not have subsets or supersets.
00227 
00228     const std::vector<PartRelation> & part_rel = part.relations();
00229 
00230     for ( std::vector<PartRelation>::const_iterator
00231           j = part_rel.begin() ; j != part_rel.end() ; ++j ) {
00232 
00233       if ( & part == j->m_root &&
00234            0 <= (* j->m_function)( entity_rank_from , entity_rank_to ,
00235                                    relation_identifier ) ) {
00236         insert_part_and_supersets( induced_parts , * j->m_target, include_supersets );
00237       }
00238     }
00239   }
00240 }
00241 
00242 //----------------------------------------------------------------------
00243 //  What are this entity's part memberships that can be deduced from
00244 //  this entity's relationship.  Can only trust 'entity_from' to be
00245 //  accurate if it is owned by the local process.
00246 
00247 void induced_part_membership( const Entity           & entity_from ,
00248                               const OrdinalVector       & omit ,
00249                                     unsigned           entity_rank_to ,
00250                                     RelationIdentifier relation_identifier ,
00251                                     OrdinalVector       & induced_parts,
00252                                     bool include_supersets)
00253 {
00254   const Bucket   & bucket_from    = entity_from.bucket();
00255   const BulkData & mesh           = BulkData::get(bucket_from);
00256   const unsigned local_proc_rank  = mesh.parallel_rank();
00257   const unsigned entity_rank_from = entity_from.entity_rank();
00258 
00259   // Only induce parts for normal (not back) relations. Can only trust
00260   // 'entity_from' to be accurate if it is owned by the local process.
00261   if ( entity_rank_to < entity_rank_from &&
00262        local_proc_rank == entity_from.owner_rank() ) {
00263     const PartVector & all_parts   = mesh.mesh_meta_data().get_parts();
00264 
00265     const std::pair<const unsigned *, const unsigned *>
00266       bucket_superset_ordinals = bucket_from.superset_part_ordinals();
00267 
00268     OrdinalVector::const_iterator omit_begin = omit.begin(),
00269                                   omit_end   = omit.end();
00270 
00271     // Contributions of the 'from' entity:
00272     for ( const unsigned * i = bucket_superset_ordinals.first ;
00273                            i != bucket_superset_ordinals.second ; ++i ) {
00274       ThrowAssertMsg( *i < all_parts.size(), "Index " << *i << " out of bounds" );
00275       Part & part = * all_parts[*i] ;
00276 
00277       if ( part.primary_entity_rank() == entity_rank_from && ! contains_ordinal( omit_begin, omit_end , *i )) {
00278         induced_part_membership( part,
00279                                  entity_rank_from ,
00280                                  entity_rank_to ,
00281                                  relation_identifier ,
00282                                  induced_parts,
00283                                  include_supersets);
00284       }
00285     }
00286   }
00287 }
00288 
00289 //----------------------------------------------------------------------
00290 
00291 void induced_part_membership( const Entity     & entity ,
00292                               const OrdinalVector & omit ,
00293                                     OrdinalVector & induced_parts,
00294                                     bool include_supersets)
00295 {
00296   for ( PairIterRelation
00297         rel = entity.relations() ; ! rel.empty() ; ++rel ) {
00298 
00299     induced_part_membership( * rel->entity() , omit ,
00300                              entity.entity_rank() ,
00301                              rel->identifier() ,
00302                              induced_parts,
00303                              include_supersets);
00304   }
00305 }
00306 
00307 //----------------------------------------------------------------------
00308 
00309 } // namespace mesh
00310 } // namespace stk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines