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 #include <cassert>
00013 
00014 #include <stk_mesh/base/Ghosting.hpp>
00015 
00016 #include <stk_mesh/baseImpl/EntityImpl.hpp>
00017 #include <stk_mesh/base/Bucket.hpp>
00018 #include <stk_mesh/base/BulkData.hpp>
00019 #include <stk_mesh/base/MetaData.hpp>
00020 
00021 namespace stk {
00022 namespace mesh {
00023 namespace impl {
00024 
00025 EntityImpl::~EntityImpl()
00026 {
00027 }
00028 
00029 
00030 EntityImpl::EntityImpl( const EntityKey & arg_key )
00031   : m_key(arg_key),
00032     m_relation(),
00033     m_comm(),
00034     m_bucket( NULL ),
00035     m_bucket_ord(0),
00036     m_owner_rank(0),
00037     m_sync_count(0),
00038     m_mod_log( EntityLogCreated )
00039 {
00040 }
00041 
00042 
00043 PairIterRelation EntityImpl::relations( unsigned rank ) const
00044 {
00045   std::vector<Relation>::const_iterator i = m_relation.begin();
00046   std::vector<Relation>::const_iterator e = m_relation.end();
00047 
00048   if ( rank ) {
00049     const Relation::raw_attr_type lo_attr = Relation::attribute( rank , 0 );
00050     i = std::lower_bound( i , e , lo_attr , LessRelation() );
00051   }
00052 
00053   const Relation::raw_attr_type hi_attr = Relation::attribute( rank + 1 , 0 );
00054   e = std::lower_bound( i , e , hi_attr , LessRelation() );
00055 
00056   return PairIterRelation( i , e );
00057 }
00058 
00059 
00060 PairIterEntityComm EntityImpl::sharing() const
00061 {
00062   EntityCommInfoVector::const_iterator i = m_comm.begin();
00063   EntityCommInfoVector::const_iterator e = m_comm.end();
00064 
00065   e = std::lower_bound( i , e , EntityCommInfo(1,0) );
00066 
00067   return PairIterEntityComm( i , e );
00068 }
00069 
00070 
00071 PairIterEntityComm EntityImpl::comm( const Ghosting & sub ) const
00072 {
00073   typedef std::vector< EntityCommInfo > EntityComm ;
00074 
00075   const EntityCommInfo s_begin( sub.ordinal() ,     0 );
00076   const EntityCommInfo s_end(   sub.ordinal() + 1 , 0 );
00077 
00078   EntityComm::const_iterator i = m_comm.begin();
00079   EntityComm::const_iterator e = m_comm.end();
00080 
00081   i = std::lower_bound( i , e , s_begin );
00082   e = std::lower_bound( i , e , s_end );
00083 
00084   return PairIterEntityComm( i , e );
00085 }
00086 
00087 
00088 bool EntityImpl::insert( const EntityCommInfo & val )
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 
00103 bool EntityImpl::erase( const EntityCommInfo & val )
00104 {
00105   std::vector< EntityCommInfo >::iterator i =
00106     std::lower_bound( m_comm.begin() , m_comm.end() , val );
00107 
00108   const bool result = i != m_comm.end() && val == *i ;
00109 
00110   if ( result ) {
00111     m_comm.erase( i );
00112   }
00113 
00114   return result ;
00115 }
00116 
00117 
00118 bool EntityImpl::erase( const Ghosting & ghost )
00119 {
00120   typedef std::vector< EntityCommInfo > EntityComm ;
00121 
00122   const EntityCommInfo s_begin( ghost.ordinal() ,     0 );
00123   const EntityCommInfo s_end(   ghost.ordinal() + 1 , 0 );
00124 
00125   EntityComm::iterator i = m_comm.begin();
00126   EntityComm::iterator e = m_comm.end();
00127 
00128   i = std::lower_bound( i , e , s_begin );
00129   e = std::lower_bound( i , e , s_end );
00130 
00131   const bool result = i != e ;
00132 
00133   if ( result ) {
00134     m_comm.erase( i , e );
00135   }
00136 
00137   return result ;
00138 }
00139 
00140 
00141 void EntityImpl::comm_clear_ghosting()
00142 {
00143   std::vector< EntityCommInfo >::iterator j = m_comm.begin();
00144   while ( j != m_comm.end() && j->ghost_id == 0 ) { ++j ; }
00145   m_comm.erase( j , m_comm.end() );
00146 }
00147 
00148 
00149 void EntityImpl::comm_clear() {
00150   m_comm.clear();
00151 }
00152 
00153 bool EntityImpl::marked_for_destruction() const {
00154   // The original implementation of this method checked bucket capacity. In
00155   // order to ensure that the addition of EntityLogDeleted does not change
00156   // behavior, we put error check here.
00157   if ( (bucket().capacity() == 0) != (m_mod_log == EntityLogDeleted) ) {
00158     std::ostringstream msg;
00159     msg << "Inconsistent destruction state; "
00160         << "destroyed entities should be in the nil bucket and vice versa.\n"
00161         << "Problem is with entity: "
00162         << print_entity_key( msg, bucket().mesh().mesh_meta_data(), key() )
00163         << "\n"
00164         << "Was in nil bucket: " << (bucket().capacity() == 0) << ", "
00165         << "was in destroyed state: " << (m_mod_log == EntityLogDeleted);
00166     throw std::runtime_error( msg.str() );
00167   }
00168   return m_mod_log == EntityLogDeleted;
00169 }
00170 
00171 namespace {
00172 
00173 bool is_degenerate_relation ( const Relation &r1 , const Relation &r2 )
00174 {
00175   return r1.attribute() == r2.attribute() && r1.entity() != r2.entity() ;
00176 }
00177 
00178 }
00179 
00180 void EntityImpl::log_resurrect()
00181 {
00182   if ( EntityLogDeleted != m_mod_log ) {
00183     std::ostringstream msg;
00184     msg << "Trying to resurrect non-deleted entity: "
00185         << print_entity_key( msg, bucket().mesh().mesh_meta_data(), key() );
00186     throw std::runtime_error( msg.str() );
00187   }
00188   m_mod_log = EntityLogModified;
00189   m_bucket = NULL;
00190 }
00191 
00192 void EntityImpl::log_created_parallel_copy()
00193 {
00194   if ( EntityLogCreated == m_mod_log ) {
00195     m_mod_log = EntityLogModified ;
00196   }
00197 }
00198 
00199 bool EntityImpl::destroy_relation( Entity& e_to )
00200 {
00201   bool destroyed_relations = false;
00202   for ( std::vector<Relation>::iterator i = m_relation.end() ;
00203         i != m_relation.begin() ; ) {
00204     --i ;
00205     if ( i->entity() == & e_to ) {
00206       i = m_relation.erase( i );
00207       destroyed_relations = true;
00208     }
00209   }
00210   return destroyed_relations;
00211 }
00212 
00213 bool EntityImpl::declare_relation( Entity & e_to,
00214                                    const unsigned local_id,
00215                                    unsigned sync_count,
00216                                    bool is_converse )
00217 {
00218   const MetaData & meta_data = bucket().mesh().mesh_meta_data();
00219 
00220   static const char method[] = "stk::mesh::impl::EntityImpl::declare_relation";
00221 
00222   const Relation new_relation( e_to , local_id );
00223 
00224   const std::vector<Relation>::iterator fe = m_relation.end();
00225         std::vector<Relation>::iterator fi = m_relation.begin();
00226 
00227   fi = std::lower_bound( fi , fe , new_relation , LessRelation() );
00228 
00229   // The ordering of the Relations allows for two situations that do
00230   // not arise often in meshes.  The first situation is 2 relations between
00231   // e_from and e_to with the same kind but different local_ids.  This
00232   // can happen if, for example, a triangle should be used as a quad.  In
00233   // this case, one node of the triangle must be two different local nodes of
00234   // the quad.  This situation is a valid state of mesh entities.
00235 
00236   // The second situation involves malformed stencils.  Given e_from, e_to1,
00237   // and e_to2, e_to1 and eto2 can share a relation with e_from with the same
00238   // kind and local_id.  This can arise, for instance, if an edge has three
00239   // nodes.  The local_id 1 of the edge may point to two different nodes.
00240   // This situation is disallowed in the mesh.  We now check for it.
00241 
00242   bool found_degenerate_relation = false;
00243   EntityKey  degenerate_key;
00244   if ( fi != fe )
00245   {
00246     bool  downstream = fi->entity_rank() < entity_rank();
00247     if ( is_degenerate_relation ( new_relation , *fi ) && downstream )
00248     {
00249       found_degenerate_relation = true;
00250       degenerate_key = fi->entity()->key();
00251     }
00252   }
00253   if ( fi != m_relation.begin() )
00254   {
00255     --fi;
00256     bool  downstream = fi->entity_rank() < entity_rank();
00257     if ( is_degenerate_relation ( new_relation , *fi ) && downstream )
00258     {
00259       found_degenerate_relation = true;
00260       degenerate_key = fi->entity()->key();
00261     }
00262     ++fi;
00263   }
00264   if ( found_degenerate_relation && !is_converse )
00265   {
00266     std::ostringstream msg ;
00267     msg << method << "( from " ;
00268     print_entity_key( msg , meta_data, key() );
00269     msg << " , to " ;
00270     print_entity_key( msg , meta_data, e_to.key() );
00271     msg << " , id " << local_id ;
00272     msg << " ) FAILED ";
00273     msg << " Relation already exists to " ;
00274     print_entity_key( msg , meta_data, degenerate_key );
00275     throw std::runtime_error( msg.str() );
00276   }
00277 
00278   // If the relation is not degenerate, we add it
00279 
00280   if ( ( !is_converse && (fe == fi ||
00281                           new_relation.attribute() != fi->attribute() ) ) ||
00282        (is_converse && (fe == fi || new_relation != *fi ) ) ) {
00283 
00284     fi = m_relation.insert( fi , new_relation );
00285 
00286     set_sync_count( sync_count );
00287 
00288     return true;
00289   }
00290   else {
00291     return false;
00292   }
00293 }
00294 
00295 } // namespace impl
00296 } // namespace mesh
00297 } // namespace stk
00298 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends