|
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 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_classic { 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_classic