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 
stk_classic::mesh::EntityKey
Integer type for the entity keys, which is an encoding of the entity type and entity identifier.
Definition: base/EntityKey.hpp:63
stk_classic::mesh::Bucket
A container for the field data of a homogeneous collection of entities.
Definition: Bucket.hpp:94
stk_classic::mesh::BulkData::generate_new_entities
void generate_new_entities(const std::vector< size_t > &requests, std::vector< Entity * > &requested_entities)
Generate a set of entites with globally unique id's.
Definition: BulkData.cpp:773
stk_classic::mesh::BulkData::parallel_size
unsigned parallel_size() const
Size of the parallel machine.
Definition: BulkData.hpp:82
stk_classic::parallel_machine_size
unsigned parallel_machine_size(ParallelMachine parallel_machine)
Member function parallel_machine_size ...
Definition: Parallel.cpp:18
stk_classic::mesh::BulkData::destroy_entity
bool destroy_entity(Entity *&entity)
Request the destruction an entity on the local process.
Definition: BulkData.cpp:698
stk_classic::mesh::Part
An application-defined subset of a problem domain.
Definition: Part.hpp:49
stk_classic::mesh::BulkData::declare_entity
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
stk_classic::parallel_machine_barrier
void parallel_machine_barrier(ParallelMachine parallel_machine)
Member function parallel_machine_barrier ...
Definition: Parallel.cpp:40
stk_classic::mesh::BulkData::change_entity_parts
void change_entity_parts(Entity &entity, const PartVector &add_parts, const PartVector &remove_parts=PartVector())
Change the parallel-locally-owned entity's part membership by adding and/or removing parts.
Definition: BulkData.hpp:249
stk_classic::ParallelMachine
MPI_Comm ParallelMachine
Definition: Parallel.hpp:32
stk_classic::mesh::verify_parallel_consistency
void verify_parallel_consistency(const MetaData &s, ParallelMachine pm)
Verify that the meta data is identical on all processors.
Definition: MetaData.cpp:501
stk_classic
Sierra Toolkit.
Definition: AlgorithmRunner.cpp:16
stk_classic::mesh::BulkData::create_ghosting
Ghosting & create_ghosting(const std::string &name)
Asymmetric parallel relations for owner-to-ghosted mesh entities.
Definition: BulkDataGhosting.cpp:38
stk_classic::mesh::BulkData::destroy_relation
bool destroy_relation(Entity &e_from, Entity &e_to, const RelationIdentifier local_id)
Remove all relations between two entities.
Definition: BulkDataRelation.cpp:191
stk_classic::PairIter
Definition: PairIter.hpp:21
stk_classic::mesh::BulkData::modification_begin
bool modification_begin()
Begin a modification phase during which the mesh bulk data could become parallel inconsistent....
Definition: BulkData.cpp:172
stk_classic::mesh::MetaData
The manager of an integrated collection of parts and fields.
Definition: MetaData.hpp:56
stk_classic::mesh::PartVector
std::vector< Part * > PartVector
Collections of parts are frequently maintained as a vector of Part pointers.
Definition: Types.hpp:31
stk_classic::mesh::entity_rank
EntityRank entity_rank(const EntityKey &key)
Given an entity key, return an entity type (rank).
Definition: base/EntityKey.hpp:161
stk_classic::mesh::BulkData::BulkData
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
stk_classic::mesh::Entity::bucket
Bucket & bucket() const
The bucket which holds this mesh entity's field data.
Definition: Entity.hpp:141
stk_classic::parallel_machine_rank
unsigned parallel_machine_rank(ParallelMachine parallel_machine)
Member function parallel_machine_rank ...
Definition: Parallel.cpp:29
stk_classic::mesh::Bucket::supersets
void supersets(PartVector &) const
This bucket is a subset of these parts.
Definition: Bucket.cpp:164
stk_classic::mesh::Entity
A fundamental unit within the discretization of a problem domain, including but not limited to nodes,...
Definition: Entity.hpp:120