Sierra Toolkit Version of the Day
EntityImpl.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 <algorithm>
00010 #include <sstream>
00011 #include <stdexcept>
00012 
00013 #include <stk_mesh/base/Ghosting.hpp>
00014 #include <stk_mesh/base/Bucket.hpp>
00015 #include <stk_mesh/base/BulkData.hpp>
00016 #include <stk_mesh/base/MetaData.hpp>
00017 
00018 #include <stk_mesh/baseImpl/EntityImpl.hpp>
00019 
00020 namespace stk {
00021 namespace mesh {
00022 namespace impl {
00023 
00024 EntityImpl::~EntityImpl()
00025 {
00026 }
00027 
00028 EntityImpl::EntityImpl( const EntityKey & arg_key )
00029   : m_key(arg_key),
00030     m_relation(),
00031     m_comm(),
00032     m_bucket( NULL ),
00033     m_bucket_ord(0),
00034     m_owner_rank(0),
00035     m_sync_count(0),
00036     m_mod_log( EntityLogCreated )
00037 {
00038   TraceIfWatching("stk::mesh::impl::EntityImpl::EntityImpl", LOG_ENTITY, arg_key);
00039 }
00040 
00041 PairIterRelation EntityImpl::relations( unsigned rank ) const
00042 {
00043   std::vector<Relation>::const_iterator i = m_relation.begin();
00044   std::vector<Relation>::const_iterator e = m_relation.end();
00045 
00046   //Nodes
00047   if ( rank != 0 ) {
00048     const Relation::raw_relation_id_type lo_attr = Relation::raw_relation_id( rank , 0 );
00049     i = std::lower_bound( i , e , lo_attr , LessRelation() );
00050   }
00051 
00052   const Relation::raw_relation_id_type hi_attr = Relation::raw_relation_id( rank + 1 , 0 );
00053   e = std::lower_bound( i , e , hi_attr , LessRelation() );
00054 
00055   return PairIterRelation( i , e );
00056 }
00057 
00058 PairIterEntityComm EntityImpl::sharing() const
00059 {
00060   EntityCommInfoVector::const_iterator i = m_comm.begin();
00061   EntityCommInfoVector::const_iterator e = m_comm.end();
00062 
00063   e = std::lower_bound( i , e , EntityCommInfo(1,     // ghost id, 1->aura
00064                                                0 ) ); // proc
00065 
00066   // Contains everything up the first aura comm (IE, only contains shared comms)
00067   return PairIterEntityComm( i , e );
00068 }
00069 
00070 PairIterEntityComm EntityImpl::comm( const Ghosting & sub ) const
00071 {
00072   typedef std::vector< EntityCommInfo > EntityComm ;
00073 
00074   const EntityCommInfo s_begin( sub.ordinal() ,     0 );
00075   const EntityCommInfo s_end(   sub.ordinal() + 1 , 0 );
00076 
00077   EntityComm::const_iterator i = m_comm.begin();
00078   EntityComm::const_iterator e = m_comm.end();
00079 
00080   i = std::lower_bound( i , e , s_begin );
00081   e = std::lower_bound( i , e , s_end );
00082 
00083   return PairIterEntityComm( i , e );
00084 }
00085 
00086 bool EntityImpl::insert( const EntityCommInfo & val )
00087 {
00088   TraceIfWatching("stk::mesh::impl::EntityImpl::insert", LOG_ENTITY, key());
00089 
00090   std::vector< EntityCommInfo >::iterator i =
00091     std::lower_bound( m_comm.begin() , m_comm.end() , val );
00092 
00093   const bool result = i == m_comm.end() || val != *i ;
00094 
00095   if ( result ) {
00096     m_comm.insert( i , val );
00097   }
00098 
00099   return result ;
00100 }
00101 
00102 bool EntityImpl::erase( const EntityCommInfo & val )
00103 {
00104   TraceIfWatching("stk::mesh::impl::EntityImpl::erase(comm)", LOG_ENTITY, key());
00105 
00106   std::vector< EntityCommInfo >::iterator i =
00107     std::lower_bound( m_comm.begin() , m_comm.end() , val );
00108 
00109   const bool result = i != m_comm.end() && val == *i ;
00110 
00111   if ( result ) {
00112     m_comm.erase( i );
00113   }
00114 
00115   return result ;
00116 }
00117 
00118 bool EntityImpl::erase( const Ghosting & ghost )
00119 {
00120   TraceIfWatching("stk::mesh::impl::EntityImpl::erase(ghost)", LOG_ENTITY, key());
00121 
00122   typedef std::vector< EntityCommInfo > EntityComm ;
00123 
00124   const EntityCommInfo s_begin( ghost.ordinal() ,     0 );
00125   const EntityCommInfo s_end(   ghost.ordinal() + 1 , 0 );
00126 
00127   EntityComm::iterator i = m_comm.begin();
00128   EntityComm::iterator e = m_comm.end();
00129 
00130   i = std::lower_bound( i , e , s_begin );
00131   e = std::lower_bound( i , e , s_end );
00132 
00133   const bool result = i != e ;
00134 
00135   if ( result ) {
00136     m_comm.erase( i , e );
00137   }
00138 
00139   return result ;
00140 }
00141 
00142 void EntityImpl::comm_clear_ghosting()
00143 {
00144   TraceIfWatching("stk::mesh::impl::EntityImpl::comm_clear_ghosting", LOG_ENTITY, key());
00145 
00146   std::vector< EntityCommInfo >::iterator j = m_comm.begin();
00147   while ( j != m_comm.end() && j->ghost_id == 0 ) { ++j ; }
00148   m_comm.erase( j , m_comm.end() );
00149 }
00150 
00151 void EntityImpl::comm_clear()
00152 {
00153   TraceIfWatching("stk::mesh::impl::EntityImpl::comm_clear", LOG_ENTITY, key());
00154   m_comm.clear();
00155 }
00156 
00157 bool EntityImpl::marked_for_destruction() const
00158 {
00159   // The original implementation of this method checked bucket capacity. In
00160   // order to ensure that the addition of EntityLogDeleted does not change
00161   // behavior, we put error check here.
00162   ThrowErrorMsgIf((bucket().capacity() == 0) != (m_mod_log == EntityLogDeleted),
00163       "Inconsistent destruction state; " <<
00164       "destroyed entities should be in the nil bucket and vice versa.\n" <<
00165       "Problem is with entity: " <<
00166       print_entity_key( MetaData::get( bucket() ), key() ) <<
00167       "\nWas in nil bucket: " << (bucket().capacity() == 0) << ", " <<
00168       "was in destroyed state: " << (m_mod_log == EntityLogDeleted) );
00169 
00170   return m_mod_log == EntityLogDeleted;
00171 }
00172 
00173 namespace {
00174 
00175 inline bool is_degenerate_relation ( const Relation &r1 , const Relation &r2 )
00176 {
00177   return r1.raw_relation_id() == r2.raw_relation_id() && r1.entity() != r2.entity() ;
00178 }
00179 
00180 }
00181 
00182 void EntityImpl::log_resurrect()
00183 {
00184   TraceIfWatching("stk::mesh::impl::EntityImpl::log_resurrect", LOG_ENTITY, key());
00185 
00186   ThrowErrorMsgIf( EntityLogDeleted != m_mod_log,
00187       "Trying to resurrect non-deleted entity: " <<
00188       print_entity_key( MetaData::get( bucket() ), key() ) );
00189 
00190   m_mod_log = EntityLogModified;
00191   m_bucket = NULL;
00192 }
00193 
00194 void EntityImpl::log_modified_and_propagate()
00195 {
00196   TraceIfWatching("stk::mesh::impl::EntityImpl::log_modified_and_propagate", LOG_ENTITY, key());
00197 
00198   // If already in modified state, return
00199   if (m_mod_log != EntityLogNoChange) {
00200     return;
00201   }
00202 
00203   // mark this entity as modified
00204   m_mod_log = EntityLogModified;
00205 
00206   // recurse on related entities w/ higher rank
00207   EntityRank rank_of_original_entity = entity_rank();
00208   for ( PairIterRelation irel = relations() ; irel.first != irel.second ; ) {
00209     --irel.second;
00210     Entity & entity = *(irel.second->entity());
00211     if ( rank_of_original_entity >= entity.entity_rank() ) {
00212       break; //we're done
00213     }
00214     else if ( entity.log_query() == EntityLogNoChange ) {
00215       entity.m_entityImpl.log_modified_and_propagate();
00216     }
00217   }
00218 
00219 }
00220 
00221 void EntityImpl::log_created_parallel_copy()
00222 {
00223   TraceIfWatching("stk::mesh::impl::EntityImpl::log_created_parallel_copy", LOG_ENTITY, key());
00224 
00225   if ( EntityLogCreated == m_mod_log ) {
00226     m_mod_log = EntityLogModified ;
00227   }
00228 }
00229 
00230 bool EntityImpl::destroy_relation( Entity& e_to, const RelationIdentifier local_id )
00231 {
00232   TraceIfWatching("stk::mesh::impl::EntityImpl::destroy_relation", LOG_ENTITY, key());
00233 
00234   bool destroyed_relations = false;
00235   for ( std::vector<Relation>::iterator
00236         i = m_relation.begin() ; i != m_relation.end() ; ++i ) {
00237     if ( i->entity() == & e_to && i->identifier() == local_id ) {
00238       i = m_relation.erase( i ); // invalidates iterators, but we're breaking so it's OK
00239       destroyed_relations = true;
00240       break;
00241     }
00242   }
00243   return destroyed_relations;
00244 }
00245 
00246 bool EntityImpl::declare_relation( Entity & e_to,
00247                                    const RelationIdentifier local_id,
00248                                    unsigned sync_count,
00249                                    bool is_back_relation )
00250 {
00251   TraceIfWatching("stk::mesh::impl::EntityImpl::declare_relation", LOG_ENTITY, key());
00252 
00253   const MetaData & meta_data = MetaData::get( bucket() );
00254 
00255   const Relation new_relation( e_to , local_id );
00256 
00257   const std::vector<Relation>::iterator rel_end   = m_relation.end();
00258         std::vector<Relation>::iterator rel_begin = m_relation.begin();
00259         std::vector<Relation>::iterator lower;
00260 
00261   lower = std::lower_bound( rel_begin , rel_end , new_relation , LessRelation() );
00262 
00263   // The ordering of the Relations allows for two situations that do
00264   // not arise often in meshes.  The first situation is 2 relations between
00265   // e_from and e_to with the same kind but different local_ids.  This
00266   // can happen if, for example, a triangle should be used as a quad.  In
00267   // this case, one node of the triangle must be two different local nodes of
00268   // the quad.  This situation is a valid state of mesh entities.
00269 
00270   // The second situation involves malformed stencils.  Given e_from, e_to1,
00271   // and e_to2, e_to1 and eto2 can share a relation with e_from with the same
00272   // kind and local_id.  This can arise, for instance, if an edge has three
00273   // nodes.  The local_id 1 of the edge may point to two different nodes.
00274   // This situation is disallowed in the mesh.  We now check for it.
00275 
00276   // "Degenerate" -> case where we have two relations whose attributes
00277   // (rel id + rel rank) match but point to different entities. It's
00278   // OK for back-relations to be degenerate because there's nothing
00279   // wrong with a node having several back-relations (with similar id)
00280   // to different elements.
00281 
00282   // Check for bad degenerate relations (degenerate forward relations)
00283   // Cannot be degenerate relation if there are no prior relations
00284   if ( !m_relation.empty() && !is_back_relation ) {
00285     // Since LessRelation takes the related entity into account, we must check
00286     // the result of lower_bound AND the iter before to be sure this isn't a
00287     // bad degenerate relation.
00288     std::vector<Relation>::iterator start, end;
00289     start = (lower == rel_begin) ? rel_begin : lower - 1;
00290     end   = (lower == rel_end)   ? rel_end   : lower + 1;
00291 
00292     for (std::vector<Relation>::iterator itr = start; itr != end; ++itr) {
00293       ThrowErrorMsgIf( is_degenerate_relation ( new_relation , *itr ),
00294                        "Could not declare relation from " <<
00295                        print_entity_key( meta_data, key() ) << " to " <<
00296                        print_entity_key( meta_data, e_to.key() ) << ", with id " <<
00297                        local_id << ". Relation already exists to " <<
00298                        print_entity_key( meta_data, itr->entity()->key() ));
00299     }
00300   }
00301 
00302   bool not_already_exists = (rel_end == lower) ||
00303     ( !is_back_relation && new_relation.raw_relation_id() != lower->raw_relation_id() ) ||
00304     ( is_back_relation && new_relation != *lower );
00305 
00306   // If the relation does not already exist, we add it
00307   if (not_already_exists) {
00308     lower = m_relation.insert( lower , new_relation );
00309 
00310     set_sync_count( sync_count );
00311 
00312     return true;
00313   }
00314   else {
00315     return false;
00316   }
00317 }
00318 
00319 } // namespace impl
00320 } // namespace mesh
00321 } // namespace stk
00322 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends