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