Sierra Toolkit Version of the Day
EntityRepository.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 <sstream>
00010 #include <stdexcept>
00011 
00012 #include <stk_mesh/baseImpl/EntityRepository.hpp>
00013 #include <stk_mesh/base/Bucket.hpp>
00014 #include <stk_mesh/base/BulkData.hpp>
00015 #include <stk_mesh/base/MetaData.hpp>
00016 
00017 namespace stk {
00018 namespace mesh {
00019 namespace impl {
00020 
00021 namespace {
00022 
00023 const MetaData & metadata_from_entity(const Entity *e) {
00024   return e->bucket().mesh().mesh_meta_data();
00025 }
00026 
00027 
00028 }
00029 
00030 EntityRepository::~EntityRepository() {
00031   try {
00032     while ( ! m_entities.empty() ) {
00033       internal_expunge_entity( m_entities.begin() );
00034     }
00035   } catch(...){}
00036 }
00037 
00038 
00039 void EntityRepository::internal_expunge_entity( EntityMap::iterator i )
00040 {
00041   const bool ok_ptr = i->second != NULL ;
00042   const bool ok_key = ok_ptr ? i->first == i->second->key() : true ;
00043 
00044   if ( ! ok_ptr || ! ok_key ) {
00045     std::ostringstream msg ;
00046     msg << "stk::mesh::baseImple::EntityRepository::internal_expunge_entity( " ;
00047     print_entity_key( msg , metadata_from_entity(i->second) , i->first );
00048     if ( ! ok_ptr ) {
00049       msg << "NULL" ;
00050     }
00051     else {
00052       msg << " != " ;
00053       print_entity_key( msg , metadata_from_entity(i->second) , i->second->key() );
00054     }
00055     msg << ") FAILED" ;
00056     throw std::runtime_error( msg.str() );
00057   }
00058 
00059   delete i->second ;
00060   i->second = NULL ;
00061   m_entities.erase( i );
00062 }
00063 
00064 std::pair<Entity*,bool>
00065 EntityRepository::internal_create_entity( const EntityKey & key )
00066 {
00067   EntityMap::value_type tmp(key,NULL);
00068 
00069   const std::pair< EntityMap::iterator , bool >
00070     insert_result = m_entities.insert( tmp );
00071 
00072   std::pair<Entity*,bool>
00073     result( insert_result.first->second , insert_result.second );
00074 
00075   if ( insert_result.second )  { // A new entity
00076     insert_result.first->second = result.first = new Entity( key );
00077   }
00078   else if ( EntityLogDeleted == result.first->log_query() ) {
00079     // resurrection
00080     result.first->m_entityImpl.log_resurrect();
00081     result.second = true;
00082   }
00083 
00084   return result ;
00085 }
00086 
00087 void EntityRepository::log_created_parallel_copy( Entity & entity )
00088 {
00089   entity.m_entityImpl.log_created_parallel_copy();
00090 }
00091 
00092 Entity * EntityRepository::get_entity(const EntityKey &key) const
00093 {
00094   const bool valid_key = entity_key_valid( key );
00095 
00096   const EntityMap::const_iterator i = m_entities.find( key );
00097 
00098   if ( ! valid_key ) {
00099     static const char method[] = "stk::mesh::BulkData::get_entity" ;
00100     std::ostringstream msg ;
00101     msg << method << "( " ;
00102     // QUESTION: If the key is invalid, then will 'i' ever be a valid iterator?
00103     if (i != m_entities.end()) {
00104       print_entity_key( msg , metadata_from_entity(i->second) , key );
00105     } else {
00106       const unsigned type = entity_rank(key);
00107       const EntityId id   = entity_id(key);
00108       msg << "Invalid key: " << type << " " << id;
00109     }
00110     msg << " INVALID KEY" ;
00111     msg << " ) FAILED" ;
00112     throw std::runtime_error( msg.str() );
00113   }
00114 
00115   return i != m_entities.end() ? i->second : NULL ;
00116 }
00117 
00118 void EntityRepository::clean_changes() {
00119 
00120   for ( EntityMap::iterator
00121       i = m_entities.begin() ; i != m_entities.end() ; )
00122   {
00123     const EntityMap::iterator j = i ;
00124     ++i ;
00125 
00126     if ( j->second->m_entityImpl.marked_for_destruction() ) {
00127       // Clear out the entities destroyed in the previous modification.
00128       // They were retained for change-logging purposes.
00129       internal_expunge_entity( j );
00130     }
00131     else {
00132       j->second->m_entityImpl.log_clear();
00133     }
00134   }
00135 }
00136 
00137 bool EntityRepository::erase_ghosting( Entity & e, const Ghosting & ghosts) const {
00138   return e.m_entityImpl.erase( ghosts );
00139 }
00140 
00141 
00142 bool EntityRepository::erase_comm_info( Entity & e, const EntityCommInfo & comm_info) const {
00143   return e.m_entityImpl.erase( comm_info );
00144 }
00145 
00146 bool EntityRepository::insert_comm_info( Entity & e, const EntityCommInfo & comm_info) const {
00147   return e.m_entityImpl.insert( comm_info );
00148 }
00149 
00150 void EntityRepository::destroy_later( Entity & e, Bucket* nil_bucket ) {
00151   if ( e.log_query() == EntityLogDeleted ) {
00152     std::ostringstream msg;
00153     msg << "Error: double deletion of entity: ";
00154     print_entity_key( msg, nil_bucket->mesh().mesh_meta_data(), e.key() );
00155     throw std::runtime_error(msg.str());
00156   }
00157 
00158   change_entity_bucket( *nil_bucket, e, 0);
00159   e.m_entityImpl.log_deleted(); //important that this come last
00160 }
00161 
00162 void EntityRepository::change_entity_bucket( Bucket & b, Entity & e,
00163                                              unsigned ordinal) {
00164   const bool modified_parts = ! e.m_entityImpl.is_bucket_valid() ||
00165                               ! b.equivalent( e.bucket() );
00166   if ( modified_parts ) {
00167     modify_and_propagate( e );
00168   }
00169   e.m_entityImpl.set_bucket_and_ordinal( &b, ordinal);
00170 }
00171 
00172 Bucket * EntityRepository::get_entity_bucket( Entity & e ) const
00173 {
00174   // Note, this allows for returning NULL bucket
00175   return e.m_entityImpl.bucket_ptr();
00176 }
00177 
00178 void EntityRepository::destroy_relation( Entity & e_from, Entity & e_to )
00179 {
00180   const MetaData & meta_data =
00181     e_from.m_entityImpl.bucket().mesh().mesh_meta_data();
00182 
00183   bool caused_change_fwd = e_from.m_entityImpl.destroy_relation(e_to);
00184 
00185   // Relationships should always be symmetrical
00186   if ( caused_change_fwd ) {
00187     bool caused_change_inv = e_to.m_entityImpl.destroy_relation(e_from);
00188     if ( ! caused_change_inv ) {
00189       std::ostringstream msg ;
00190       msg << "destroy_relation( from "
00191           << print_entity_key( msg , meta_data, e_from.key() )
00192           << " , to "
00193           << print_entity_key( msg , meta_data, e_to.key() )
00194           << " ) FAILED"
00195           << " Internal error - could not destroy inverse relation" ;
00196       throw std::runtime_error( msg.str() );
00197     }
00198   }
00199 
00200   if ( caused_change_fwd ) {
00201     modify_and_propagate( e_to );
00202     modify_and_propagate( e_from );
00203   }
00204 }
00205 
00206 void EntityRepository::declare_relation( Entity & e_from,
00207                                          Entity & e_to,
00208                                          const unsigned local_id,
00209                                          unsigned sync_count )
00210 {
00211   const MetaData & meta_data =
00212     e_from.m_entityImpl.bucket().mesh().mesh_meta_data();
00213 
00214   bool caused_change_fwd =
00215     e_from.m_entityImpl.declare_relation( e_to, local_id, sync_count);
00216 
00217   // Relationships should always be symmetrical
00218   if ( caused_change_fwd ) {
00219 
00220     // the setup for the converse relationship works slightly differently
00221     bool is_converse = true;
00222     bool caused_change_inv =
00223       e_to.m_entityImpl.declare_relation( e_from, local_id, sync_count,
00224                                           is_converse );
00225 
00226     if ( ! caused_change_inv ) {
00227       std::ostringstream msg ;
00228       msg << "declare_relation( from "
00229           << print_entity_key( msg , meta_data, e_from.key() )
00230           << " , to "
00231           << print_entity_key( msg , meta_data, e_to.key() )
00232           << " , id " << local_id
00233           << " ) FAILED"
00234           << " Internal error - could not create inverse relation" ;
00235       throw std::runtime_error( msg.str() );
00236     }
00237   }
00238 
00239   if ( caused_change_fwd ) {
00240     modify_and_propagate( e_to );
00241     modify_and_propagate( e_from );
00242   }
00243 }
00244 
00245 void EntityRepository::modify_and_propagate( Entity & modified_entity ) const
00246 {
00247   // mark this entity as modified
00248   modified_entity.m_entityImpl.log_modified();
00249 
00250   // recurse on related entities w/ higher rank
00251   EntityRank rank_of_original_entity = modified_entity.entity_rank();
00252   for ( PairIterRelation irel = modified_entity.relations();
00253         !irel.empty();
00254         ++irel ) {
00255     if ( rank_of_original_entity < irel->entity_rank() ) {
00256       modify_and_propagate( *(irel->entity()) );
00257     }
00258   }
00259 }
00260 
00261 } // namespace impl
00262 } // namespace mesh
00263 } // namespace stk
00264 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends