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 boost::fast_pool_allocator<Entity>& entity_allocator()
00022 {
00023   static boost::fast_pool_allocator<Entity> entity_pool_allocator;
00024   return entity_pool_allocator;
00025 }
00026 
00027 #ifdef SIERRA_MIGRATION
00028 boost::fast_pool_allocator<fmwk_attributes>& fmwk_attr_allocator()
00029 {
00030   static boost::fast_pool_allocator<fmwk_attributes> fmwk_attr_allocator;
00031   return fmwk_attr_allocator;
00032 }
00033 #endif
00034 
00035 Entity* EntityRepository::allocate_entity(bool use_pool)
00036 {
00037   if (use_pool) {
00038     static Entity tmp_entity;
00039     Entity* new_entity = entity_allocator().allocate();
00040     entity_allocator().construct(new_entity, tmp_entity);
00041     return new_entity;
00042   }
00043   //else
00044   return new Entity;
00045 }
00046 
00047 #ifdef SIERRA_MIGRATION
00048 fmwk_attributes* allocate_fmwk_attr(bool use_pool)
00049 {
00050   if (use_pool) {
00051     static fmwk_attributes tmp_attributes;
00052     fmwk_attributes* fmwk_attrs = fmwk_attr_allocator().allocate();
00053     fmwk_attr_allocator().construct(fmwk_attrs, tmp_attributes);
00054     return fmwk_attrs;
00055   }
00056   //else
00057   return new fmwk_attributes;
00058 }
00059 #endif
00060 
00061 void destroy_entity(Entity* entity, bool use_pool)
00062 {
00063   if (use_pool) {
00064     entity_allocator().destroy(entity);
00065     entity_allocator().deallocate(entity, 1);
00066     return;
00067   }
00068   //else
00069   delete entity;
00070 }
00071 
00072 #ifdef SIERRA_MIGRATION
00073 void destroy_fmwk_attr(fmwk_attributes* fmwk_attr, bool use_pool)
00074 {
00075   if (use_pool) {
00076     fmwk_attr_allocator().destroy(fmwk_attr);
00077     fmwk_attr_allocator().deallocate(fmwk_attr, 1);
00078     return;
00079   }
00080   //else
00081   delete fmwk_attr;
00082 }
00083 #endif
00084 
00085 void release_all_entity_memory(bool use_pool)
00086 {
00087   if (use_pool) {
00088     boost::singleton_pool<boost::fast_pool_allocator_tag, sizeof(Entity)>::release_memory();
00089   }
00090 }
00091 
00092 #ifdef SIERRA_MIGRATION
00093 void release_all_fmwk_attr_memory(bool use_pool)
00094 {
00095   if (use_pool) {
00096     boost::singleton_pool<boost::fast_pool_allocator_tag, sizeof(fmwk_attributes)>::release_memory();
00097   }
00098 }
00099 #endif
00100 
00101 EntityRepository::~EntityRepository()
00102 {
00103   try {
00104     while ( ! m_entities.empty() ) {
00105       internal_expunge_entity( m_entities.begin() );
00106     }
00107   } catch(...){}
00108 
00109   release_all_entity_memory(m_use_pool);
00110 #ifdef SIERRA_MIGRATION
00111   release_all_fmwk_attr_memory(m_use_pool);
00112 #endif
00113 }
00114 
00115 void EntityRepository::internal_expunge_entity( EntityMap::iterator i )
00116 {
00117   TraceIfWatching("stk::mesh::impl::EntityRepository::internal_expunge_entity", LOG_ENTITY, i->first);
00118 
00119   ThrowErrorMsgIf( i->second == NULL,
00120                    "For key " << entity_rank(i->first) << " " <<
00121                    entity_id(i->first) << ", value was NULL");
00122 
00123   ThrowErrorMsgIf( i->first != i->second->key(),
00124     "Key " << print_entity_key(MetaData::get( *i->second ), i->first) <<
00125     " != " << print_entity_key(i->second));
00126 
00127   Entity* deleted_entity = i->second;
00128 
00129 #ifdef SIERRA_MIGRATION
00130   destroy_fmwk_attr(deleted_entity->m_fmwk_attrs, m_use_pool);
00131 #endif
00132   destroy_entity(deleted_entity, m_use_pool);
00133   i->second = NULL;
00134   m_entities.erase( i );
00135 }
00136 
00137 Entity*
00138 EntityRepository::internal_allocate_entity(EntityKey entity_key)
00139 {
00140   Entity* new_entity = allocate_entity(m_use_pool);
00141   new_entity->set_key(entity_key);
00142 #ifdef SIERRA_MIGRATION
00143   fmwk_attributes* fmwk_attrs = allocate_fmwk_attr(m_use_pool);
00144   new_entity->m_fmwk_attrs = fmwk_attrs;
00145 #endif
00146   return new_entity;
00147 }
00148 
00149 std::pair<Entity*,bool>
00150 EntityRepository::internal_create_entity( const EntityKey & key )
00151 {
00152   TraceIfWatching("stk::mesh::impl::EntityRepository::internal_create_entity", LOG_ENTITY, key);
00153 
00154   EntityMap::value_type tmp(key,NULL);
00155 
00156   const std::pair< EntityMap::iterator , bool >
00157     insert_result = m_entities.insert( tmp );
00158 
00159   std::pair<Entity*,bool>
00160     result( insert_result.first->second , insert_result.second );
00161 
00162   if ( insert_result.second )  { // A new entity
00163     Entity* new_entity = internal_allocate_entity(key);
00164     insert_result.first->second = result.first = new_entity;
00165   }
00166   else if ( EntityLogDeleted == result.first->log_query() ) {
00167     // resurrection
00168     result.first->m_entityImpl.log_resurrect();
00169     result.second = true;
00170   }
00171 
00172   return result ;
00173 }
00174 
00175 void EntityRepository::log_created_parallel_copy( Entity & entity )
00176 {
00177   TraceIfWatching("stk::mesh::impl::EntityRepository::log_created_parallel_copy", LOG_ENTITY, entity.key());
00178 
00179   entity.m_entityImpl.log_created_parallel_copy();
00180 }
00181 
00182 Entity * EntityRepository::get_entity(const EntityKey &key) const
00183 {
00184   ThrowErrorMsgIf( ! entity_key_valid( key ),
00185       "Invalid key: " << entity_rank(key) << " " << entity_id(key));
00186 
00187   const EntityMap::const_iterator i = m_entities.find( key );
00188 
00189   return i != m_entities.end() ? i->second : NULL ;
00190 }
00191 
00192 void EntityRepository::clean_changes()
00193 {
00194   TraceIf("stk::mesh::impl::EntityRepository::clean_changes", LOG_ENTITY);
00195 
00196   for ( EntityMap::iterator
00197       i = m_entities.begin() ; i != m_entities.end() ; )
00198   {
00199     const EntityMap::iterator j = i ;
00200     ++i ;
00201 
00202     if ( j->second->m_entityImpl.marked_for_destruction() ) {
00203       // Clear out the entities destroyed in the previous modification.
00204       // They were retained for change-logging purposes.
00205       internal_expunge_entity( j );
00206     }
00207     else {
00208       j->second->m_entityImpl.log_clear();
00209     }
00210   }
00211 }
00212 
00213 bool EntityRepository::erase_ghosting( Entity & e, const Ghosting & ghosts) const
00214 {
00215   TraceIfWatching("stk::mesh::impl::EntityRepository::erase_ghosting", LOG_ENTITY, e.key());
00216 
00217   return e.m_entityImpl.erase( ghosts );
00218 }
00219 
00220 bool EntityRepository::erase_comm_info( Entity & e, const EntityCommInfo & comm_info) const
00221 {
00222   TraceIfWatching("stk::mesh::impl::EntityRepository::erase_comm_info", LOG_ENTITY, e.key());
00223 
00224   return e.m_entityImpl.erase( comm_info );
00225 }
00226 
00227 bool EntityRepository::insert_comm_info( Entity & e, const EntityCommInfo & comm_info) const
00228 {
00229   TraceIfWatching("stk::mesh::impl::EntityRepository::insert_comm_info", LOG_ENTITY, e.key());
00230 
00231   return e.m_entityImpl.insert( comm_info );
00232 }
00233 
00234 void EntityRepository::destroy_later( Entity & e, Bucket* nil_bucket )
00235 {
00236   TraceIfWatching("stk::mesh::impl::EntityRepository::destroy_later", LOG_ENTITY, e.key());
00237 
00238   ThrowErrorMsgIf( e.log_query() == EntityLogDeleted,
00239                    "double deletion of entity: " << print_entity_key( e ));
00240 
00241   change_entity_bucket( *nil_bucket, e, 0);
00242   e.m_entityImpl.log_deleted(); //important that this come last
00243 }
00244 
00245 void EntityRepository::change_entity_bucket( Bucket & b, Entity & e,
00246                                              unsigned ordinal)
00247 {
00248   TraceIfWatching("stk::mesh::impl::EntityRepository::change_entity_bucket", LOG_ENTITY, e.key());
00249   DiagIfWatching(LOG_ENTITY, e.key(), "New bucket: " << b << ", ordinal: " << ordinal);
00250 
00251   const bool modified_parts = ! e.m_entityImpl.is_bucket_valid() ||
00252                               ! b.equivalent( e.bucket() );
00253   if ( modified_parts ) {
00254     e.m_entityImpl.log_modified_and_propagate();
00255   }
00256   e.m_entityImpl.set_bucket_and_ordinal( &b, ordinal);
00257 }
00258 
00259 Bucket * EntityRepository::get_entity_bucket( Entity & e ) const
00260 {
00261   // Note, this allows for returning NULL bucket
00262   return e.m_entityImpl.bucket_ptr();
00263 }
00264 
00265 bool EntityRepository::destroy_relation( Entity & e_from,
00266                                          Entity & e_to,
00267                                          const RelationIdentifier local_id )
00268 {
00269   TraceIfWatching("stk::mesh::impl::EntityRepository::destroy_relation", LOG_ENTITY, e_from.key());
00270 
00271   bool caused_change_fwd = e_from.m_entityImpl.destroy_relation(e_to, local_id);
00272 
00273   // Relationships should always be symmetrical
00274   if ( caused_change_fwd ) {
00275     bool caused_change_inv = e_to.m_entityImpl.destroy_relation(e_from, local_id);
00276     ThrowErrorMsgIf( !caused_change_inv,
00277         " Internal error - could not destroy inverse relation of " <<
00278         print_entity_key( e_from ) << " to " << print_entity_key( e_to ) <<
00279         " with local relation id of " << local_id);
00280   }
00281 
00282   // It is critical that the modification be done AFTER the relations are
00283   // changed so that the propagation can happen correctly.
00284   if ( caused_change_fwd ) {
00285     e_to.m_entityImpl.log_modified_and_propagate();
00286     e_from.m_entityImpl.log_modified_and_propagate();
00287   }
00288 
00289   return caused_change_fwd;
00290 }
00291 
00292 void EntityRepository::declare_relation( Entity & e_from,
00293                                          Entity & e_to,
00294                                          const RelationIdentifier local_id,
00295                                          unsigned sync_count )
00296 {
00297   TraceIfWatching("stk::mesh::impl::EntityRepository::declare_relation", LOG_ENTITY, e_from.key());
00298 
00299   bool caused_change_fwd =
00300     e_from.m_entityImpl.declare_relation( e_to, local_id, sync_count);
00301 
00302   // Relationships should always be symmetrical
00303   if ( caused_change_fwd ) {
00304 
00305     // the setup for the converse relationship works slightly differently
00306     bool is_converse = true;
00307     bool caused_change_inv =
00308       e_to.m_entityImpl.declare_relation( e_from, local_id, sync_count,
00309                                           is_converse );
00310 
00311     ThrowErrorMsgIf( !caused_change_inv,
00312         " Internal error - could not create inverse relation of " <<
00313         print_entity_key( e_from ) << " to " << print_entity_key( e_to ));
00314   }
00315 
00316   // It is critical that the modification be done AFTER the relations are
00317   // added so that the propagation can happen correctly.
00318   if ( caused_change_fwd ) {
00319     e_to.m_entityImpl.log_modified_and_propagate();
00320     e_from.m_entityImpl.log_modified_and_propagate();
00321   }
00322 }
00323 
00324 void EntityRepository::update_entity_key(EntityKey key, Entity & entity)
00325 {
00326   EntityKey old_key = entity.key();
00327 
00328   EntityMap::iterator old_itr = m_entities.find( old_key );
00329 
00330   EntityMap::iterator itr = m_entities.find(key);
00331   if (itr != m_entities.end()) {
00332     Entity* key_entity = itr->second;
00333     ThrowRequireMsg( key_entity->log_query() == EntityLogDeleted, "update_entity_key ERROR: non-deleted entity already present for new key (" << key.rank()<<","<<key.id()<<")");
00334 
00335     //We found an entity with 'key', we'll change its key to old_key and then
00336     //entity (old_itr) will adopt key.
00337 
00338     key_entity->m_entityImpl.update_key(old_key);
00339     //key_entity is already marked for deletion
00340 
00341     old_itr->second->m_entityImpl.update_key(key);
00342 
00343     //We also need to swap the entities on these map iterators so that
00344     //they map to the right keys:
00345     itr->second = old_itr->second;
00346     old_itr->second = key_entity;
00347   }
00348   else {
00349     m_entities.insert(std::make_pair(key,&entity));
00350 
00351     entity.m_entityImpl.update_key(key);
00352 
00353     old_itr->second = internal_allocate_entity(old_key);
00354 
00355     old_itr->second->m_entityImpl.log_deleted();
00356   }
00357 }
00358 
00359 } // namespace impl
00360 } // namespace mesh
00361 } // namespace stk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines