Sierra Toolkit  Version of the Day
BulkData.cpp
1 /*------------------------------------------------------------------------*/
2 /* Copyright 2010, 2011 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 
13 #include <stdexcept>
14 #include <iostream>
15 #include <sstream>
16 #include <algorithm>
17 
18 #include <stk_util/environment/ReportHandler.hpp>
19 
20 #include <stk_util/util/StaticAssert.hpp>
21 
22 #include <stk_util/diag/Trace.hpp>
23 #include <stk_util/parallel/ParallelComm.hpp>
24 #include <stk_util/parallel/ParallelReduce.hpp>
25 
26 #include <stk_mesh/base/Bucket.hpp>
27 #include <stk_mesh/base/BulkData.hpp>
28 #include <stk_mesh/base/MetaData.hpp>
29 #include <stk_mesh/base/Comm.hpp>
30 #include <stk_mesh/base/FieldData.hpp>
31 
32 #include <boost/foreach.hpp>
33 
34 namespace stk_classic {
35 namespace mesh {
36 
37 namespace {
38 
39 std::vector< parallel::DistributedIndex::KeySpan>
40 convert_entity_keys_to_spans( const MetaData & meta )
41 {
42  // Make sure the distributed index can handle the EntityKey
43 
44  enum { OK = StaticAssert<
45  SameType< EntityKey::raw_key_type,
46  parallel::DistributedIndex::KeyType >::value >::OK };
47 
48  // Default constructed EntityKey has all bits set.
49 
50  const EntityKey invalid_key ;
51  const EntityId min_id = 1 ;
52  const EntityId max_id = invalid_key.id();
53 
54  const size_t rank_count = meta.entity_rank_count();
55 
56  std::vector< parallel::DistributedIndex::KeySpan> spans( rank_count );
57 
58  for ( size_t rank = 0 ; rank < rank_count ; ++rank ) {
59  EntityKey key_min( rank , min_id );
60  EntityKey key_max( rank , max_id );
61  spans[rank].first = key_min.raw_key();
62  spans[rank].second = key_max.raw_key();
63  }
64 
65  return spans ;
66 }
67 
68 void ensure_part_superset_consistency( const Entity& entity )
69 {
70  std::ostringstream errs;
71  PartVector parts;
72  Bucket& bucket = entity.bucket();
73  bucket.supersets(parts);
74  BOOST_FOREACH(Part* part, parts) {
75  const PartVector& supersets = part->supersets();
76  BOOST_FOREACH(Part* superset, supersets) {
77  if (!bucket.member(*superset)) {
78  errs << " Due to being a member part " << part->name() << ", should have been a member of " << superset->name() << std::endl;
79  }
80  }
81  }
82  ThrowRequireMsg( errs.str() == "",
83  "Entity " << print_entity_key(entity) << " has bad part list:\n" << errs.str() );
84 }
85 
86 }
87 
88 //----------------------------------------------------------------------
89 
90 BulkData::BulkData( MetaData & mesh_meta_data ,
91  ParallelMachine parallel ,
92  unsigned bucket_max_size ,
93  bool use_memory_pool )
94  : m_entities_index( parallel, convert_entity_keys_to_spans(mesh_meta_data) ),
95  m_entity_repo(use_memory_pool),
96  m_bucket_repository(
97  *this, bucket_max_size,
98  mesh_meta_data.entity_rank_count(),
99  m_entity_repo
100  ),
101  m_entity_comm(),
102  m_ghosting(),
103 
104  m_mesh_meta_data( mesh_meta_data ),
105  m_parallel_machine( parallel ),
106  m_parallel_size( parallel_machine_size( parallel ) ),
107  m_parallel_rank( parallel_machine_rank( parallel ) ),
108  m_sync_count( 0 ),
109  m_sync_state( MODIFIABLE ),
110  m_meta_data_verified( false ),
111  m_optimize_buckets(false),
112  m_mesh_finalized(false)
113 {
114  create_ghosting( "shared" );
115  create_ghosting( "shared_aura" );
116 
117  m_sync_state = SYNCHRONIZED ;
118 }
119 
120 BulkData::~BulkData()
121 {
122  try {
123  while ( ! m_ghosting.empty() ) {
124  delete m_ghosting.back();
125  m_ghosting.pop_back();
126  }
127  } catch(...){}
128 
129  try { m_entity_comm.clear(); } catch(...){}
130 
131 }
132 
133 //----------------------------------------------------------------------
134 //----------------------------------------------------------------------
135 
136 void BulkData::require_ok_to_modify() const
137 {
138  ThrowRequireMsg( m_sync_state != SYNCHRONIZED,
139  "NOT in the ok-to-modify state" );
140 }
141 
142 void BulkData::require_entity_owner( const Entity & entity ,
143  unsigned owner ) const
144 {
145  const bool error_not_owner = owner != entity.owner_rank() ;
146 
147  ThrowRequireMsg( !error_not_owner,
148  "Entity " << print_entity_key(entity) << " owner is " <<
149  entity.owner_rank() << ", expected " << owner);
150 }
151 
152 void BulkData::require_good_rank_and_id(EntityRank ent_rank, EntityId ent_id) const
153 {
154  const size_t rank_count = m_mesh_meta_data.entity_rank_count();
155  const bool ok_id = entity_id_valid(ent_id);
156  const bool ok_rank = ent_rank < rank_count ;
157 
158  ThrowRequireMsg( ok_rank,
159  "Bad key rank: " << ent_rank << " for id " << ent_id );
160 
161  ThrowRequireMsg( ok_id, "Bad key id for key: " <<
162  print_entity_key(m_mesh_meta_data, EntityKey(ent_rank, ent_id) ) );
163 }
164 
165 void BulkData::require_metadata_committed() const
166 {
167  ThrowRequireMsg( m_mesh_meta_data.is_commit(), "MetaData not committed." );
168 }
169 
170 //----------------------------------------------------------------------
171 
173 {
174  Trace_("stk_classic::mesh::BulkData::modification_begin");
175 
176  parallel_machine_barrier( m_parallel_machine );
177 
178  ThrowRequireMsg( m_mesh_finalized == false, "Unable to modifiy, BulkData has been finalized.");
179 
180  if ( m_sync_state == MODIFIABLE && m_mesh_finalized == false ) return false ;
181 
182  if ( ! m_meta_data_verified ) {
183  require_metadata_committed();
184 
185  if (parallel_size() > 1) {
186  verify_parallel_consistency( m_mesh_meta_data , m_parallel_machine );
187  }
188 
189  m_meta_data_verified = true ;
190 
191  m_bucket_repository.declare_nil_bucket();
192  }
193  else {
194  ++m_sync_count ;
195 
196  // Clear out the previous transaction information
197  // m_transaction_log.flush();
198 
199  m_entity_repo.clean_changes();
200  }
201 
202  m_sync_state = MODIFIABLE ;
203 
204  return true ;
205 }
206 
207 //----------------------------------------------------------------------
208 //----------------------------------------------------------------------
209 // The add_parts must be full ordered and consistent,
210 // i.e. no bad parts, all supersets included, and
211 // owner & used parts match the owner value.
212 
213 //----------------------------------------------------------------------
214 
215 Entity & BulkData::declare_entity( EntityRank ent_rank , EntityId ent_id ,
216  const PartVector & parts )
217 {
218  require_ok_to_modify();
219 
220  require_good_rank_and_id(ent_rank, ent_id);
221 
222  EntityKey key( ent_rank , ent_id );
223  TraceIfWatching("stk_classic::mesh::BulkData::declare_entity", LOG_ENTITY, key);
224  DiagIfWatching(LOG_ENTITY, key, "declaring entity with parts " << parts);
225 
226  std::pair< Entity * , bool > result = m_entity_repo.internal_create_entity( key );
227 
228  Entity* declared_entity = result.first;
229 
230  if ( result.second ) {
231  // A new application-created entity
232  m_entity_repo.set_entity_owner_rank( *declared_entity, m_parallel_rank);
233  m_entity_repo.set_entity_sync_count( *declared_entity, m_sync_count);
234  DiagIfWatching(LOG_ENTITY, key, "new entity: " << *declared_entity);
235  }
236  else {
237  // An existing entity, the owner must match.
238  require_entity_owner( *declared_entity , m_parallel_rank );
239  DiagIfWatching(LOG_ENTITY, key, "existing entity: " << *declared_entity);
240  }
241 
242  //------------------------------
243 
244  Part * const owns = & m_mesh_meta_data.locally_owned_part();
245 
246  std::vector<Part*> rem ;
247  std::vector<Part*> add( parts );
248  add.push_back( owns );
249 
250  change_entity_parts( *declared_entity , add , rem );
251 
252  // m_transaction_log.insert_entity ( *(result.first) );
253 
254  return *declared_entity ;
255 }
256 
257 void BulkData::change_entity_id( EntityId id, Entity & entity)
258 {
259  require_ok_to_modify();
260  require_good_rank_and_id(entity.entity_rank(),id);
261 
262  EntityKey key(entity.entity_rank(),id);
263  EntityKey old_key = entity.key();
264 
265  m_entity_repo.update_entity_key(key,entity);
266 
267  //We also need to swap the comm-vectors for these entities:
268  entity_comm_swap(key, old_key);
269 }
270 
271 //----------------------------------------------------------------------
272 
273 // TODO Change the methods below to requirements (private, const invariant checkers)
274 
275 // Do not allow any of the induced part memberships to explicitly
276 // appear in the add or remove parts lists.
277 // 1) Intersection part
278 // 2) PartRelation target part
279 // 3) Part that does not match the entity rank.
280 
281 void BulkData::internal_verify_change_parts( const MetaData & meta ,
282  const Entity & entity ,
283  const PartVector & parts ) const
284 {
285  const std::vector<std::string> & rank_names = meta.entity_rank_names();
286  const EntityRank undef_rank = InvalidEntityRank;
287  const EntityRank entity_rank = entity.entity_rank();
288 
289  bool ok = true ;
290  std::ostringstream msg ;
291 
292  for ( PartVector::const_iterator
293  i = parts.begin() ; i != parts.end() ; ++i ) {
294 
295  const Part * const p = *i ;
296  const unsigned part_rank = p->primary_entity_rank();
297 
298  bool intersection_ok, rel_target_ok, rank_ok;
299  internal_basic_part_check(p, entity_rank, undef_rank, intersection_ok, rel_target_ok, rank_ok);
300 
301  if ( !intersection_ok || !rel_target_ok || !rank_ok ) {
302  if ( ok ) {
303  ok = false ;
304  msg << "change parts for entity " << print_entity_key( entity );
305  msg << " , { " ;
306  }
307  else {
308  msg << " , " ;
309  }
310 
311  msg << p->name() << "[" ;
312  if ( part_rank < rank_names.size() ) {
313  msg << rank_names[ part_rank ];
314  }
315  else {
316  msg << part_rank ;
317  }
318  msg << "] " ;
319  if ( !intersection_ok ) { msg << "is_intersection " ; }
320  if ( !rel_target_ok ) { msg << "is_relation_target " ; }
321  if ( !rank_ok ) { msg << "is_bad_rank " ; }
322  }
323  }
324 
325  ThrowErrorMsgIf( !ok, msg.str() << "}" );
326 }
327 
328 void BulkData::internal_verify_change_parts( const MetaData & meta ,
329  const Entity & entity ,
330  const OrdinalVector & parts ) const
331 {
332  const std::vector<std::string> & rank_names = meta.entity_rank_names();
333  const EntityRank undef_rank = InvalidEntityRank;
334  const EntityRank entity_rank = entity.entity_rank();
335 
336  bool ok = true ;
337  std::ostringstream msg ;
338 
339  for ( OrdinalVector::const_iterator
340  i = parts.begin() ; i != parts.end() ; ++i ) {
341 
342  const Part * const p = meta.get_parts()[*i] ;
343  const unsigned part_rank = p->primary_entity_rank();
344 
345  bool intersection_ok, rel_target_ok, rank_ok;
346  internal_basic_part_check(p, entity_rank, undef_rank, intersection_ok, rel_target_ok, rank_ok);
347 
348  if ( !intersection_ok || !rel_target_ok || !rank_ok ) {
349  if ( ok ) {
350  ok = false ;
351  msg << "change parts for entity " << print_entity_key( entity );
352  msg << " , { " ;
353  }
354  else {
355  msg << " , " ;
356  }
357 
358  msg << p->name() << "[" ;
359  if ( part_rank < rank_names.size() ) {
360  msg << rank_names[ part_rank ];
361  }
362  else {
363  msg << part_rank ;
364  }
365  msg << "] " ;
366  if ( !intersection_ok ) { msg << "is_intersection " ; }
367  if ( !rel_target_ok ) { msg << "is_relation_target " ; }
368  if ( !rank_ok ) { msg << "is_bad_rank " ; }
369  }
370  }
371 
372  ThrowErrorMsgIf( !ok, msg.str() << "}" );
373 }
374 
375 //----------------------------------------------------------------------
376 
377 namespace {
378 
379 void filter_out( std::vector<unsigned> & vec ,
380  const PartVector & parts ,
381  PartVector & removed )
382 {
383  std::vector<unsigned>::iterator i , j ;
384  i = j = vec.begin();
385 
386  PartVector::const_iterator ip = parts.begin() ;
387 
388  while ( j != vec.end() && ip != parts.end() ) {
389  Part * const p = *ip ;
390  if ( p->mesh_meta_data_ordinal() < *j ) { ++ip ; }
391  else if ( *j < p->mesh_meta_data_ordinal() ) { *i = *j ; ++i ; ++j ; }
392  else {
393  removed.push_back( p );
394  ++j ;
395  ++ip ;
396  }
397  }
398 
399  if ( i != j ) { vec.erase( i , j ); }
400 }
401 
402 void filter_out( std::vector<unsigned> & vec ,
403  const OrdinalVector & parts ,
404  OrdinalVector & removed )
405 {
406  std::vector<unsigned>::iterator i , j ;
407  i = j = vec.begin();
408 
409  OrdinalVector::const_iterator ip = parts.begin() ;
410 
411  while ( j != vec.end() && ip != parts.end() ) {
412  if ( *ip < *j ) { ++ip ; }
413  else if ( *j < *ip ) { *i = *j ; ++i ; ++j ; }
414  else {
415  removed.push_back( *ip );
416  ++j ;
417  ++ip ;
418  }
419  }
420 
421  if ( i != j ) { vec.erase( i , j ); }
422 }
423 
424 void merge_in( std::vector<unsigned> & vec , const PartVector & parts )
425 {
426  std::vector<unsigned>::iterator i = vec.begin();
427  PartVector::const_iterator ip = parts.begin() ;
428 
429  for ( ; i != vec.end() && ip != parts.end() ; ++i ) {
430 
431  const unsigned ord = (*ip)->mesh_meta_data_ordinal();
432 
433  if ( ord <= *i ) {
434  if ( ord < *i ) { i = vec.insert( i , ord ); }
435  // Now have: ord == *i
436  ++ip ;
437  }
438  }
439 
440  for ( ; ip != parts.end() ; ++ip ) {
441  const unsigned ord = (*ip)->mesh_meta_data_ordinal();
442  vec.push_back( ord );
443  }
444 }
445 
446 void merge_in( std::vector<unsigned> & vec , const OrdinalVector & parts )
447 {
448  std::vector<unsigned>::iterator i = vec.begin();
449  OrdinalVector::const_iterator ip = parts.begin() ;
450 
451  for ( ; i != vec.end() && ip != parts.end() ; ++i ) {
452 
453  const unsigned ord = *ip;
454 
455  if ( ord <= *i ) {
456  if ( ord < *i ) { i = vec.insert( i , ord ); }
457  // Now have: ord == *i
458  ++ip ;
459  }
460  }
461 
462  for ( ; ip != parts.end() ; ++ip ) {
463  vec.push_back( *ip );
464  }
465 }
466 
467 }
468 
469 // The 'add_parts' and 'remove_parts' are complete and disjoint.
470 // Changes need to have parallel resolution during
471 // modification_end.
472 
473 void BulkData::internal_change_entity_parts(
474  Entity & entity ,
475  const PartVector & add_parts ,
476  const PartVector & remove_parts )
477 {
478  TraceIfWatching("stk_classic::mesh::BulkData::internal_change_entity_parts", LOG_ENTITY, entity.key());
479  DiagIfWatching(LOG_ENTITY, entity.key(), "entity state: " << entity);
480  DiagIfWatching(LOG_ENTITY, entity.key(), "add_parts: " << add_parts);
481  DiagIfWatching(LOG_ENTITY, entity.key(), "remove_parts: " << remove_parts);
482 
483  Bucket * const k_old = m_entity_repo.get_entity_bucket( entity );
484 
485  const unsigned i_old = entity.bucket_ordinal() ;
486 
487  if ( k_old && k_old->member_all( add_parts ) &&
488  ! k_old->member_any( remove_parts ) ) {
489  // Is already a member of all add_parts,
490  // is not a member of any remove_parts,
491  // thus nothing to do.
492  return ;
493  }
494 
495  PartVector parts_removed ;
496 
497  OrdinalVector parts_total ; // The final part list
498 
499  //--------------------------------
500 
501  if ( k_old ) {
502  // Keep any of the existing bucket's parts
503  // that are not a remove part.
504  // This will include the 'intersection' parts.
505  //
506  // These parts are properly ordered and unique.
507 
508  const std::pair<const unsigned *, const unsigned*>
509  bucket_parts = k_old->superset_part_ordinals();
510 
511  const unsigned * parts_begin = bucket_parts.first;
512  const unsigned * parts_end = bucket_parts.second;
513 
514  const unsigned num_bucket_parts = parts_end - parts_begin;
515  parts_total.reserve( num_bucket_parts + add_parts.size() );
516  parts_total.insert( parts_total.begin(), parts_begin , parts_end);
517 
518  if ( !remove_parts.empty() ) {
519  parts_removed.reserve(remove_parts.size());
520  filter_out( parts_total , remove_parts , parts_removed );
521  }
522  }
523  else {
524  parts_total.reserve(add_parts.size());
525  }
526 
527  if ( !add_parts.empty() ) {
528  merge_in( parts_total , add_parts );
529  }
530 
531  if ( parts_total.empty() ) {
532  // Always a member of the universal part.
533  const unsigned univ_ord =
534  m_mesh_meta_data.universal_part().mesh_meta_data_ordinal();
535  parts_total.push_back( univ_ord );
536  }
537 
538  //--------------------------------
539  // Move the entity to the new bucket.
540 
541  Bucket * k_new =
542  m_bucket_repository.declare_bucket(
543  entity.entity_rank(),
544  parts_total.size(),
545  & parts_total[0] ,
546  m_mesh_meta_data.get_fields()
547  );
548 
549  // If changing buckets then copy its field values from old to new bucket
550 
551  if ( k_old ) {
552  m_bucket_repository.copy_fields( *k_new , k_new->size() , *k_old , i_old );
553  }
554  else {
555  m_bucket_repository.initialize_fields( *k_new , k_new->size() );
556  }
557 
558  // Set the new bucket
559  m_entity_repo.change_entity_bucket( *k_new, entity, k_new->size() );
560  m_bucket_repository.add_entity_to_bucket( entity, *k_new );
561 
562  // If changing buckets then remove the entity from the bucket,
563  if ( k_old && k_old->capacity() > 0) { m_bucket_repository.remove_entity( k_old , i_old ); }
564 
565  // Update the change counter to the current cycle.
566  m_entity_repo.set_entity_sync_count( entity, m_sync_count );
567 
568  // Propagate part changes through the entity's relations.
569 
570  internal_propagate_part_changes( entity , parts_removed );
571 
572 #ifndef NDEBUG
573  //ensure_part_superset_consistency( entity );
574 #endif
575 }
576 
577 void BulkData::internal_change_entity_parts(
578  Entity & entity ,
579  const OrdinalVector & add_parts ,
580  const OrdinalVector & remove_parts,
581  bool always_propagate_internal_changes )
582 {
583  TraceIfWatching("stk_classic::mesh::BulkData::internal_change_entity_parts", LOG_ENTITY, entity.key());
584  DiagIfWatching(LOG_ENTITY, entity.key(), "entity state: " << entity);
585  DiagIfWatching(LOG_ENTITY, entity.key(), "add_parts: " << add_parts);
586  DiagIfWatching(LOG_ENTITY, entity.key(), "remove_parts: " << remove_parts);
587 
588  Bucket * const k_old = m_entity_repo.get_entity_bucket( entity );
589 
590  const unsigned i_old = entity.bucket_ordinal() ;
591 
592  if ( k_old && k_old->member_all( add_parts ) &&
593  ! k_old->member_any( remove_parts ) ) {
594  // Is already a member of all add_parts,
595  // is not a member of any remove_parts,
596  // thus nothing to do.
597  return ;
598  }
599 
600  OrdinalVector parts_removed ;
601 
602  OrdinalVector parts_total ; // The final part list
603 
604  //--------------------------------
605 
606  if ( k_old ) {
607  // Keep any of the existing bucket's parts
608  // that are not a remove part.
609  // This will include the 'intersection' parts.
610  //
611  // These parts are properly ordered and unique.
612 
613  const std::pair<const unsigned *, const unsigned*>
614  bucket_parts = k_old->superset_part_ordinals();
615 
616  const unsigned * parts_begin = bucket_parts.first;
617  const unsigned * parts_end = bucket_parts.second;
618 
619  const unsigned num_bucket_parts = parts_end - parts_begin;
620  parts_total.reserve( num_bucket_parts + add_parts.size() );
621  parts_total.insert( parts_total.begin(), parts_begin , parts_end);
622 
623  if ( !remove_parts.empty() ) {
624  parts_removed.reserve(remove_parts.size());
625  filter_out( parts_total , remove_parts , parts_removed );
626  }
627  }
628  else {
629  parts_total.reserve(add_parts.size());
630  }
631 
632  if ( !add_parts.empty() ) {
633  merge_in( parts_total , add_parts );
634  }
635 
636  if ( parts_total.empty() ) {
637  // Always a member of the universal part.
638  const unsigned univ_ord =
639  m_mesh_meta_data.universal_part().mesh_meta_data_ordinal();
640  parts_total.push_back( univ_ord );
641  }
642 
643  //--------------------------------
644  // Move the entity to the new bucket.
645 
646  Bucket * k_new =
647  m_bucket_repository.declare_bucket(
648  entity.entity_rank(),
649  parts_total.size(),
650  & parts_total[0] ,
651  m_mesh_meta_data.get_fields()
652  );
653 
654  // If changing buckets then copy its field values from old to new bucket
655 
656  if ( k_old ) {
657  m_bucket_repository.copy_fields( *k_new , k_new->size() , *k_old , i_old );
658  }
659  else {
660  m_bucket_repository.initialize_fields( *k_new , k_new->size() );
661  }
662 
663  // Set the new bucket
664  m_entity_repo.change_entity_bucket( *k_new, entity, k_new->size() );
665  m_bucket_repository.add_entity_to_bucket( entity, *k_new );
666 
667  // If changing buckets then remove the entity from the bucket,
668  if ( k_old && k_old->capacity() > 0) { m_bucket_repository.remove_entity( k_old , i_old ); }
669 
670  // Update the change counter to the current cycle.
671  m_entity_repo.set_entity_sync_count( entity, m_sync_count );
672 
673  // Propagate part changes through the entity's relations.
674  //(Only propagate part changes for parts which have a primary-entity-rank that matches
675  // the entity's rank. Other parts don't get induced...)
676 
677  const PartVector& all_parts = m_mesh_meta_data.get_parts();
678 
679  OrdinalVector rank_parts_removed;
680  for(OrdinalVector::const_iterator pr=parts_removed.begin(), prend=parts_removed.end(); pr!=prend; ++pr) {
681  if (all_parts[*pr]->primary_entity_rank() == entity.entity_rank()) {
682  rank_parts_removed.push_back(*pr);
683  }
684  }
685 
686  if (always_propagate_internal_changes ||
687  !rank_parts_removed.empty() || !m_mesh_meta_data.get_field_relations().empty()) {
688  internal_propagate_part_changes( entity , rank_parts_removed );
689  }
690 
691 #ifndef NDEBUG
692  //ensure_part_superset_consistency( entity );
693 #endif
694 }
695 
696 //----------------------------------------------------------------------
697 
698 bool BulkData::destroy_entity( Entity * & entity_in )
699 {
700  Entity & entity = *entity_in ;
701 
702  TraceIfWatching("stk_classic::mesh::BulkData::destroy_entity", LOG_ENTITY, entity.key());
703  DiagIfWatching(LOG_ENTITY, entity.key(), "entity state: " << entity);
704 
705  require_ok_to_modify( );
706 
707  bool has_upward_relation = false ;
708 
709  for ( PairIterRelation
710  irel = entity.relations() ;
711  ! irel.empty() && ! has_upward_relation ; ++irel ) {
712 
713  has_upward_relation = entity.entity_rank() <= irel->entity_rank();
714  }
715 
716  if ( has_upward_relation ) { return false ; }
717 
718  if ( EntityLogDeleted == entity.log_query() ) {
719  // Cannot already be destroyed.
720  return false ;
721  }
722  //------------------------------
723  // Immediately remove it from relations and buckets.
724  // Postpone deletion until modification_end to be sure that
725  // 1) No attempt is made to re-create it.
726  // 2) Parallel index is cleaned up.
727  // 3) Parallel sharing is cleaned up.
728  // 4) Parallel ghosting is cleaned up.
729  //
730  // Must clean up the parallel lists before fully deleting the entity.
731 
732  // It is important that relations be destroyed in reverse order so that
733  // the higher (back) relations are destroyed first.
734  while ( ! entity.relations().empty() ) {
735  destroy_relation( entity ,
736  * entity.relations().back().entity(),
737  entity.relations().back().identifier());
738  }
739 
740  // We need to save these items and call remove_entity AFTER the call to
741  // destroy_later because remove_entity may destroy the bucket
742  // which would cause problems in m_entity_repo.destroy_later because it
743  // makes references to the entity's original bucket.
744  Bucket& orig_bucket = entity.bucket();
745  unsigned orig_bucket_ordinal = entity.bucket_ordinal();
746 
747  // Set the bucket to 'bucket_nil' which:
748  // 1) has no parts at all
749  // 2) has no field data
750  // 3) has zero capacity
751  //
752  // This keeps the entity-bucket methods from catastrophically failing
753  // with a bad bucket pointer.
754 
755  m_entity_repo.destroy_later( entity, m_bucket_repository.get_nil_bucket() );
756 
757  m_bucket_repository.remove_entity( &orig_bucket , orig_bucket_ordinal );
758 
759  // Add destroyed entity to the transaction
760  // m_transaction_log.delete_entity ( *entity_in );
761 
762  // Set the calling entity-pointer to NULL;
763  // hopefully the user-code will clean up any outstanding
764  // references to this entity.
765 
766  entity_in = NULL ;
767 
768  return true ;
769 }
770 
771 //----------------------------------------------------------------------
772 
773 void BulkData::generate_new_entities(const std::vector<size_t>& requests,
774  std::vector<Entity *>& requested_entities)
775 {
776  Trace_("stk_classic::mesh::BulkData::generate_new_entities");
777 
778  typedef stk_classic::parallel::DistributedIndex::KeyType KeyType;
779  std::vector< std::vector<KeyType> >
780  requested_key_types;
781  m_entities_index.generate_new_keys(requests, requested_key_types);
782 
783  //generating 'owned' entities
784  Part * const owns = & m_mesh_meta_data.locally_owned_part();
785 
786  std::vector<Part*> rem ;
787  std::vector<Part*> add;
788  add.push_back( owns );
789 
790  requested_entities.clear();
791  unsigned cnt=0;
792  for (std::vector< std::vector<KeyType> >::const_iterator itr = requested_key_types.begin(); itr != requested_key_types.end(); ++itr) {
793  const std::vector<KeyType>& key_types = *itr;
794  for (std::vector<KeyType>::const_iterator
795  kitr = key_types.begin(); kitr != key_types.end(); ++kitr) {
796  ++cnt;
797  }
798  }
799  requested_entities.reserve(cnt);
800 
801  for (std::vector< std::vector<KeyType> >::const_iterator itr = requested_key_types.begin(); itr != requested_key_types.end(); ++itr) {
802  const std::vector<KeyType>& key_types = *itr;
803  for (std::vector<KeyType>::const_iterator
804  kitr = key_types.begin(); kitr != key_types.end(); ++kitr) {
805  EntityKey key(&(*kitr));
806  std::pair<Entity *, bool> result = m_entity_repo.internal_create_entity(key);
807 
808  //if an entity is declare with the declare_entity function in
809  //the same modification cycle as the generate_new_entities
810  //function, and it happens to generate a key that was declare
811  //previously in the same cycle it is an error
812  ThrowErrorMsgIf( ! result.second,
813  "Generated " << print_entity_key(m_mesh_meta_data, key) <<
814  " which was already used in this modification cycle.");
815 
816  // A new application-created entity
817 
818  Entity* new_entity = result.first;
819 
820  m_entity_repo.set_entity_owner_rank( *new_entity, m_parallel_rank);
821  m_entity_repo.set_entity_sync_count( *new_entity, m_sync_count);
822 
823  //add entity to 'owned' part
824  change_entity_parts( *new_entity , add , rem );
825  requested_entities.push_back(new_entity);
826  }
827  }
828 }
829 
830 
831 //----------------------------------------------------------------------
832 //----------------------------------------------------------------------
833 
834 } // namespace mesh
835 } // namespace stk_classic
836 
void verify_parallel_consistency(const MetaData &s, ParallelMachine pm)
Verify that the meta data is identical on all processors.
Definition: MetaData.cpp:501
The manager of an integrated collection of parts and fields.
Definition: MetaData.hpp:56
Ghosting & create_ghosting(const std::string &name)
Asymmetric parallel relations for owner-to-ghosted mesh entities.
bool destroy_relation(Entity &e_from, Entity &e_to, const RelationIdentifier local_id)
Remove all relations between two entities.
Bucket & bucket() const
The bucket which holds this mesh entity&#39;s field data.
Definition: Entity.hpp:141
BulkData(MetaData &mesh_meta_data, ParallelMachine parallel, unsigned bucket_max_size=1000, bool use_memory_pool=true)
Construct mesh bulk data manager conformal to the given meta data manager and will distribute bulk da...
Definition: BulkData.cpp:90
Integer type for the entity keys, which is an encoding of the entity type and entity identifier...
An application-defined subset of a problem domain.
Definition: Part.hpp:49
unsigned parallel_machine_rank(ParallelMachine parallel_machine)
Member function parallel_machine_rank ...
Definition: Parallel.cpp:29
void change_entity_parts(Entity &entity, const PartVector &add_parts, const PartVector &remove_parts=PartVector())
Change the parallel-locally-owned entity&#39;s part membership by adding and/or removing parts...
Definition: BulkData.hpp:249
unsigned parallel_size() const
Size of the parallel machine.
Definition: BulkData.hpp:82
bool modification_begin()
Begin a modification phase during which the mesh bulk data could become parallel inconsistent. This is a parallel synchronous call. The first time this method is called the mesh meta data is verified to be committed and parallel consistent. An exception is thrown if this verification fails.
Definition: BulkData.cpp:172
unsigned parallel_machine_size(ParallelMachine parallel_machine)
Member function parallel_machine_size ...
Definition: Parallel.cpp:18
A fundamental unit within the discretization of a problem domain, including but not limited to nodes...
Definition: Entity.hpp:120
Sierra Toolkit.
void supersets(PartVector &) const
This bucket is a subset of these parts.
Definition: Bucket.cpp:164
MPI_Comm ParallelMachine
Definition: Parallel.hpp:32
void parallel_machine_barrier(ParallelMachine parallel_machine)
Member function parallel_machine_barrier ...
Definition: Parallel.cpp:40
Entity & declare_entity(EntityRank ent_rank, EntityId ent_id, const PartVector &parts)
Create or retrieve a locally owned entity of a given rank and id.
Definition: BulkData.cpp:215
std::vector< Part *> PartVector
Collections of parts are frequently maintained as a vector of Part pointers.
Definition: Types.hpp:31
void generate_new_entities(const std::vector< size_t > &requests, std::vector< Entity *> &requested_entities)
Generate a set of entites with globally unique id&#39;s.
Definition: BulkData.cpp:773
A container for the field data of a homogeneous collection of entities.
Definition: Bucket.hpp:94
EntityRank entity_rank(const EntityKey &key)
Given an entity key, return an entity type (rank).
bool destroy_entity(Entity *&entity)
Request the destruction an entity on the local process.
Definition: BulkData.cpp:698