Sierra Toolkit  Version of the Day
EntityRepository.cpp
1 /*------------------------------------------------------------------------*/
2 /* Copyright 2010 Sandia Corporation. */
3 /* Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive */
4 /* license for use of this work by or on behalf of the U.S. Government. */
5 /* Export of this program may require a license from the */
6 /* United States Government. */
7 /*------------------------------------------------------------------------*/
8 
9 #include <sstream>
10 #include <stdexcept>
11 
12 #include <stk_mesh/baseImpl/EntityRepository.hpp>
13 #include <stk_mesh/base/Bucket.hpp>
14 #include <stk_mesh/base/BulkData.hpp>
15 #include <stk_mesh/base/MetaData.hpp>
16 
17 namespace stk_classic {
18 namespace mesh {
19 namespace impl {
20 
21 boost::fast_pool_allocator<Entity>& entity_allocator()
22 {
23  static boost::fast_pool_allocator<Entity> entity_pool_allocator;
24  return entity_pool_allocator;
25 }
26 
27 #ifdef SIERRA_MIGRATION
28 boost::fast_pool_allocator<fmwk_attributes>& fmwk_attr_allocator()
29 {
30  static boost::fast_pool_allocator<fmwk_attributes> fmwk_attr_allocator;
31  return fmwk_attr_allocator;
32 }
33 #endif
34 
35 Entity* EntityRepository::allocate_entity(bool use_pool)
36 {
37  if (use_pool) {
38  static Entity tmp_entity;
39  Entity* new_entity = entity_allocator().allocate();
40  entity_allocator().construct(new_entity, tmp_entity);
41  return new_entity;
42  }
43  //else
44  return new Entity;
45 }
46 
47 #ifdef SIERRA_MIGRATION
48 fmwk_attributes* allocate_fmwk_attr(bool use_pool)
49 {
50  if (use_pool) {
51  static fmwk_attributes tmp_attributes;
52  fmwk_attributes* fmwk_attrs = fmwk_attr_allocator().allocate();
53  fmwk_attr_allocator().construct(fmwk_attrs, tmp_attributes);
54  return fmwk_attrs;
55  }
56  //else
57  return new fmwk_attributes;
58 }
59 #endif
60 
61 void destroy_entity(Entity* entity, bool use_pool)
62 {
63  if (use_pool) {
64  entity_allocator().destroy(entity);
65  entity_allocator().deallocate(entity, 1);
66  return;
67  }
68  //else
69  delete entity;
70 }
71 
72 #ifdef SIERRA_MIGRATION
73 void destroy_fmwk_attr(fmwk_attributes* fmwk_attr, bool use_pool)
74 {
75  if (use_pool) {
76  fmwk_attr_allocator().destroy(fmwk_attr);
77  fmwk_attr_allocator().deallocate(fmwk_attr, 1);
78  return;
79  }
80  //else
81  delete fmwk_attr;
82 }
83 #endif
84 
85 void release_all_entity_memory(bool use_pool)
86 {
87  if (use_pool) {
88  boost::singleton_pool<boost::fast_pool_allocator_tag, sizeof(Entity)>::release_memory();
89  }
90 }
91 
92 #ifdef SIERRA_MIGRATION
93 void release_all_fmwk_attr_memory(bool use_pool)
94 {
95  if (use_pool) {
96  boost::singleton_pool<boost::fast_pool_allocator_tag, sizeof(fmwk_attributes)>::release_memory();
97  }
98 }
99 #endif
100 
101 EntityRepository::~EntityRepository()
102 {
103  try {
104  while ( ! m_entities.empty() ) {
105  internal_expunge_entity( m_entities.begin() );
106  }
107  } catch(...){}
108 
109  release_all_entity_memory(m_use_pool);
110 #ifdef SIERRA_MIGRATION
111  release_all_fmwk_attr_memory(m_use_pool);
112 #endif
113 }
114 
115 void EntityRepository::internal_expunge_entity( EntityMap::iterator i )
116 {
117  TraceIfWatching("stk_classic::mesh::impl::EntityRepository::internal_expunge_entity", LOG_ENTITY, i->first);
118 
119  ThrowErrorMsgIf( i->second == NULL,
120  "For key " << entity_rank(i->first) << " " <<
121  entity_id(i->first) << ", value was NULL");
122 
123  ThrowErrorMsgIf( i->first != i->second->key(),
124  "Key " << print_entity_key(MetaData::get( *i->second ), i->first) <<
125  " != " << print_entity_key(i->second));
126 
127  Entity* deleted_entity = i->second;
128 
129 #ifdef SIERRA_MIGRATION
130  destroy_fmwk_attr(deleted_entity->m_fmwk_attrs, m_use_pool);
131 #endif
132  destroy_entity(deleted_entity, m_use_pool);
133  i->second = NULL;
134  m_entities.erase( i );
135 }
136 
137 Entity*
138 EntityRepository::internal_allocate_entity(EntityKey entity_key)
139 {
140  Entity* new_entity = allocate_entity(m_use_pool);
141  new_entity->set_key(entity_key);
142 #ifdef SIERRA_MIGRATION
143  fmwk_attributes* fmwk_attrs = allocate_fmwk_attr(m_use_pool);
144  new_entity->m_fmwk_attrs = fmwk_attrs;
145 #endif
146  return new_entity;
147 }
148 
149 std::pair<Entity*,bool>
150 EntityRepository::internal_create_entity( const EntityKey & key )
151 {
152  TraceIfWatching("stk_classic::mesh::impl::EntityRepository::internal_create_entity", LOG_ENTITY, key);
153 
154  EntityMap::value_type tmp(key,NULL);
155 
156  const std::pair< EntityMap::iterator , bool >
157  insert_result = m_entities.insert( tmp );
158 
159  std::pair<Entity*,bool>
160  result( insert_result.first->second , insert_result.second );
161 
162  if ( insert_result.second ) { // A new entity
163  Entity* new_entity = internal_allocate_entity(key);
164  insert_result.first->second = result.first = new_entity;
165  }
166  else if ( EntityLogDeleted == result.first->log_query() ) {
167  // resurrection
168  result.first->m_entityImpl.log_resurrect();
169  result.second = true;
170  }
171 
172  return result ;
173 }
174 
175 void EntityRepository::log_created_parallel_copy( Entity & entity )
176 {
177  TraceIfWatching("stk_classic::mesh::impl::EntityRepository::log_created_parallel_copy", LOG_ENTITY, entity.key());
178 
179  entity.m_entityImpl.log_created_parallel_copy();
180 }
181 
182 Entity * EntityRepository::get_entity(const EntityKey &key) const
183 {
184  ThrowErrorMsgIf( ! entity_key_valid( key ),
185  "Invalid key: " << entity_rank(key) << " " << entity_id(key));
186 
187  const EntityMap::const_iterator i = m_entities.find( key );
188 
189  return i != m_entities.end() ? i->second : NULL ;
190 }
191 
192 void EntityRepository::clean_changes()
193 {
194  TraceIf("stk_classic::mesh::impl::EntityRepository::clean_changes", LOG_ENTITY);
195 
196  for ( EntityMap::iterator
197  i = m_entities.begin() ; i != m_entities.end() ; )
198  {
199  const EntityMap::iterator j = i ;
200  ++i ;
201 
202  if ( j->second->m_entityImpl.marked_for_destruction() ) {
203  // Clear out the entities destroyed in the previous modification.
204  // They were retained for change-logging purposes.
205  internal_expunge_entity( j );
206  }
207  else {
208  j->second->m_entityImpl.log_clear();
209  }
210  }
211 }
212 
213 bool EntityRepository::erase_ghosting( Entity & e, const Ghosting & ghosts) const
214 {
215  TraceIfWatching("stk_classic::mesh::impl::EntityRepository::erase_ghosting", LOG_ENTITY, e.key());
216 
217  return e.m_entityImpl.erase( ghosts );
218 }
219 
220 bool EntityRepository::erase_comm_info( Entity & e, const EntityCommInfo & comm_info) const
221 {
222  TraceIfWatching("stk_classic::mesh::impl::EntityRepository::erase_comm_info", LOG_ENTITY, e.key());
223 
224  return e.m_entityImpl.erase( comm_info );
225 }
226 
227 bool EntityRepository::insert_comm_info( Entity & e, const EntityCommInfo & comm_info) const
228 {
229  TraceIfWatching("stk_classic::mesh::impl::EntityRepository::insert_comm_info", LOG_ENTITY, e.key());
230 
231  return e.m_entityImpl.insert( comm_info );
232 }
233 
234 void EntityRepository::destroy_later( Entity & e, Bucket* nil_bucket )
235 {
236  TraceIfWatching("stk_classic::mesh::impl::EntityRepository::destroy_later", LOG_ENTITY, e.key());
237 
238  ThrowErrorMsgIf( e.log_query() == EntityLogDeleted,
239  "double deletion of entity: " << print_entity_key( e ));
240 
241  change_entity_bucket( *nil_bucket, e, 0);
242  e.m_entityImpl.log_deleted(); //important that this come last
243 }
244 
245 void EntityRepository::change_entity_bucket( Bucket & b, Entity & e,
246  unsigned ordinal)
247 {
248  TraceIfWatching("stk_classic::mesh::impl::EntityRepository::change_entity_bucket", LOG_ENTITY, e.key());
249  DiagIfWatching(LOG_ENTITY, e.key(), "New bucket: " << b << ", ordinal: " << ordinal);
250 
251  const bool modified_parts = ! e.m_entityImpl.is_bucket_valid() ||
252  ! b.equivalent( e.bucket() );
253  if ( modified_parts ) {
254  e.m_entityImpl.log_modified_and_propagate();
255  }
256  e.m_entityImpl.set_bucket_and_ordinal( &b, ordinal);
257 }
258 
259 Bucket * EntityRepository::get_entity_bucket( Entity & e ) const
260 {
261  // Note, this allows for returning NULL bucket
262  return e.m_entityImpl.bucket_ptr();
263 }
264 
265 bool EntityRepository::destroy_relation( Entity & e_from,
266  Entity & e_to,
267  const RelationIdentifier local_id )
268 {
269  TraceIfWatching("stk_classic::mesh::impl::EntityRepository::destroy_relation", LOG_ENTITY, e_from.key());
270 
271  bool caused_change_fwd = e_from.m_entityImpl.destroy_relation(e_to, local_id);
272 
273  // Relationships should always be symmetrical
274  if ( caused_change_fwd ) {
275  bool caused_change_inv = e_to.m_entityImpl.destroy_relation(e_from, local_id);
276  ThrowErrorMsgIf( !caused_change_inv,
277  " Internal error - could not destroy inverse relation of " <<
278  print_entity_key( e_from ) << " to " << print_entity_key( e_to ) <<
279  " with local relation id of " << local_id);
280  }
281 
282  // It is critical that the modification be done AFTER the relations are
283  // changed so that the propagation can happen correctly.
284  if ( caused_change_fwd ) {
285  e_to.m_entityImpl.log_modified_and_propagate();
286  e_from.m_entityImpl.log_modified_and_propagate();
287  }
288 
289  return caused_change_fwd;
290 }
291 
292 void EntityRepository::declare_relation( Entity & e_from,
293  Entity & e_to,
294  const RelationIdentifier local_id,
295  unsigned sync_count )
296 {
297  TraceIfWatching("stk_classic::mesh::impl::EntityRepository::declare_relation", LOG_ENTITY, e_from.key());
298 
299  bool caused_change_fwd =
300  e_from.m_entityImpl.declare_relation( e_to, local_id, sync_count);
301 
302  // Relationships should always be symmetrical
303  if ( caused_change_fwd ) {
304 
305  // the setup for the converse relationship works slightly differently
306  bool is_converse = true;
307  bool caused_change_inv =
308  e_to.m_entityImpl.declare_relation( e_from, local_id, sync_count,
309  is_converse );
310 
311  ThrowErrorMsgIf( !caused_change_inv,
312  " Internal error - could not create inverse relation of " <<
313  print_entity_key( e_from ) << " to " << print_entity_key( e_to ));
314  }
315 
316  // It is critical that the modification be done AFTER the relations are
317  // added so that the propagation can happen correctly.
318  if ( caused_change_fwd ) {
319  e_to.m_entityImpl.log_modified_and_propagate();
320  e_from.m_entityImpl.log_modified_and_propagate();
321  }
322 }
323 
324 void EntityRepository::update_entity_key(EntityKey key, Entity & entity)
325 {
326  EntityKey old_key = entity.key();
327 
328  EntityMap::iterator old_itr = m_entities.find( old_key );
329 
330  EntityMap::iterator itr = m_entities.find(key);
331  if (itr != m_entities.end()) {
332  Entity* key_entity = itr->second;
333  ThrowRequireMsg( key_entity->log_query() == EntityLogDeleted, "update_entity_key ERROR: non-deleted entity already present for new key (" << key.rank()<<","<<key.id()<<")");
334 
335  //We found an entity with 'key', we'll change its key to old_key and then
336  //entity (old_itr) will adopt key.
337 
338  key_entity->m_entityImpl.update_key(old_key);
339  //key_entity is already marked for deletion
340 
341  old_itr->second->m_entityImpl.update_key(key);
342 
343  //We also need to swap the entities on these map iterators so that
344  //they map to the right keys:
345  itr->second = old_itr->second;
346  old_itr->second = key_entity;
347  }
348  else {
349  m_entities.insert(std::make_pair(key,&entity));
350 
351  entity.m_entityImpl.update_key(key);
352 
353  old_itr->second = internal_allocate_entity(old_key);
354 
355  old_itr->second->m_entityImpl.log_deleted();
356  }
357 }
358 
359 } // namespace impl
360 } // namespace mesh
361 } // namespace stk_classic
bool entity_key_valid(const EntityKey &key)
Query if an entity key is valid.
EntityId entity_id(const EntityKey &key)
Given an entity key, return the identifier for the entity.
Sierra Toolkit.
EntityRank entity_rank(const EntityKey &key)
Given an entity key, return an entity type (rank).