18 #include <stk_util/environment/ReportHandler.hpp>
20 #include <stk_util/util/StaticAssert.hpp>
22 #include <stk_util/diag/Trace.hpp>
23 #include <stk_util/parallel/ParallelComm.hpp>
24 #include <stk_util/parallel/ParallelReduce.hpp>
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>
32 #include <boost/foreach.hpp>
39 std::vector< parallel::DistributedIndex::KeySpan>
40 convert_entity_keys_to_spans(
const MetaData & meta )
44 enum { OK = StaticAssert<
45 SameType< EntityKey::raw_key_type,
46 parallel::DistributedIndex::KeyType >::value >::OK };
50 const EntityKey invalid_key ;
51 const EntityId min_id = 1 ;
52 const EntityId max_id = invalid_key.id();
54 const size_t rank_count = meta.entity_rank_count();
56 std::vector< parallel::DistributedIndex::KeySpan> spans( rank_count );
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();
68 void ensure_part_superset_consistency(
const Entity& entity )
70 std::ostringstream errs;
72 Bucket& bucket = entity.
bucket();
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;
82 ThrowRequireMsg( errs.str() ==
"",
83 "Entity " << print_entity_key(entity) <<
" has bad part list:\n" << errs.str() );
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),
97 *this, bucket_max_size,
98 mesh_meta_data.entity_rank_count(),
104 m_mesh_meta_data( mesh_meta_data ),
105 m_parallel_machine( parallel ),
109 m_sync_state( MODIFIABLE ),
110 m_meta_data_verified( false ),
111 m_optimize_buckets(false),
112 m_mesh_finalized(false)
117 m_sync_state = SYNCHRONIZED ;
120 BulkData::~BulkData()
123 while ( ! m_ghosting.empty() ) {
124 delete m_ghosting.back();
125 m_ghosting.pop_back();
129 try { m_entity_comm.clear(); }
catch(...){}
136 void BulkData::require_ok_to_modify()
const
138 ThrowRequireMsg( m_sync_state != SYNCHRONIZED,
139 "NOT in the ok-to-modify state" );
142 void BulkData::require_entity_owner(
const Entity & entity ,
143 unsigned owner )
const
145 const bool error_not_owner = owner != entity.owner_rank() ;
147 ThrowRequireMsg( !error_not_owner,
148 "Entity " << print_entity_key(entity) <<
" owner is " <<
149 entity.owner_rank() <<
", expected " << owner);
152 void BulkData::require_good_rank_and_id(EntityRank ent_rank, EntityId ent_id)
const
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 ;
158 ThrowRequireMsg( ok_rank,
159 "Bad key rank: " << ent_rank <<
" for id " << ent_id );
161 ThrowRequireMsg( ok_id,
"Bad key id for key: " <<
162 print_entity_key(m_mesh_meta_data, EntityKey(ent_rank, ent_id) ) );
165 void BulkData::require_metadata_committed()
const
167 ThrowRequireMsg( m_mesh_meta_data.is_commit(),
"MetaData not committed." );
174 Trace_(
"stk_classic::mesh::BulkData::modification_begin");
178 ThrowRequireMsg( m_mesh_finalized ==
false,
"Unable to modifiy, BulkData has been finalized.");
180 if ( m_sync_state == MODIFIABLE && m_mesh_finalized ==
false )
return false ;
182 if ( ! m_meta_data_verified ) {
183 require_metadata_committed();
189 m_meta_data_verified = true ;
191 m_bucket_repository.declare_nil_bucket();
199 m_entity_repo.clean_changes();
202 m_sync_state = MODIFIABLE ;
218 require_ok_to_modify();
220 require_good_rank_and_id(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);
226 std::pair< Entity * , bool > result = m_entity_repo.internal_create_entity( key );
228 Entity* declared_entity = result.first;
230 if ( result.second ) {
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);
238 require_entity_owner( *declared_entity , m_parallel_rank );
239 DiagIfWatching(LOG_ENTITY, key,
"existing entity: " << *declared_entity);
244 Part *
const owns = & m_mesh_meta_data.locally_owned_part();
246 std::vector<Part*> rem ;
247 std::vector<Part*> add( parts );
248 add.push_back( owns );
254 return *declared_entity ;
257 void BulkData::change_entity_id( EntityId
id,
Entity & entity)
259 require_ok_to_modify();
260 require_good_rank_and_id(entity.entity_rank(),id);
265 m_entity_repo.update_entity_key(key,entity);
268 entity_comm_swap(key, old_key);
281 void BulkData::internal_verify_change_parts(
const MetaData & meta ,
282 const Entity & entity ,
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();
290 std::ostringstream msg ;
292 for ( PartVector::const_iterator
293 i = parts.begin() ; i != parts.end() ; ++i ) {
295 const Part *
const p = *i ;
296 const unsigned part_rank = p->primary_entity_rank();
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);
301 if ( !intersection_ok || !rel_target_ok || !rank_ok ) {
304 msg <<
"change parts for entity " << print_entity_key( entity );
311 msg << p->name() <<
"[" ;
312 if ( part_rank < rank_names.size() ) {
313 msg << rank_names[ part_rank ];
319 if ( !intersection_ok ) { msg <<
"is_intersection " ; }
320 if ( !rel_target_ok ) { msg <<
"is_relation_target " ; }
321 if ( !rank_ok ) { msg <<
"is_bad_rank " ; }
325 ThrowErrorMsgIf( !ok, msg.str() <<
"}" );
328 void BulkData::internal_verify_change_parts(
const MetaData & meta ,
329 const Entity & entity ,
330 const OrdinalVector & parts )
const
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();
337 std::ostringstream msg ;
339 for ( OrdinalVector::const_iterator
340 i = parts.begin() ; i != parts.end() ; ++i ) {
342 const Part *
const p = meta.get_parts()[*i] ;
343 const unsigned part_rank = p->primary_entity_rank();
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);
348 if ( !intersection_ok || !rel_target_ok || !rank_ok ) {
351 msg <<
"change parts for entity " << print_entity_key( entity );
358 msg << p->name() <<
"[" ;
359 if ( part_rank < rank_names.size() ) {
360 msg << rank_names[ part_rank ];
366 if ( !intersection_ok ) { msg <<
"is_intersection " ; }
367 if ( !rel_target_ok ) { msg <<
"is_relation_target " ; }
368 if ( !rank_ok ) { msg <<
"is_bad_rank " ; }
372 ThrowErrorMsgIf( !ok, msg.str() <<
"}" );
379 void filter_out( std::vector<unsigned> & vec ,
383 std::vector<unsigned>::iterator i , j ;
386 PartVector::const_iterator ip = parts.begin() ;
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 ; }
393 removed.push_back( p );
399 if ( i != j ) { vec.erase( i , j ); }
402 void filter_out( std::vector<unsigned> & vec ,
403 const OrdinalVector & parts ,
404 OrdinalVector & removed )
406 std::vector<unsigned>::iterator i , j ;
409 OrdinalVector::const_iterator ip = parts.begin() ;
411 while ( j != vec.end() && ip != parts.end() ) {
412 if ( *ip < *j ) { ++ip ; }
413 else if ( *j < *ip ) { *i = *j ; ++i ; ++j ; }
415 removed.push_back( *ip );
421 if ( i != j ) { vec.erase( i , j ); }
424 void merge_in( std::vector<unsigned> & vec ,
const PartVector & parts )
426 std::vector<unsigned>::iterator i = vec.begin();
427 PartVector::const_iterator ip = parts.begin() ;
429 for ( ; i != vec.end() && ip != parts.end() ; ++i ) {
431 const unsigned ord = (*ip)->mesh_meta_data_ordinal();
434 if ( ord < *i ) { i = vec.insert( i , ord ); }
440 for ( ; ip != parts.end() ; ++ip ) {
441 const unsigned ord = (*ip)->mesh_meta_data_ordinal();
442 vec.push_back( ord );
446 void merge_in( std::vector<unsigned> & vec ,
const OrdinalVector & parts )
448 std::vector<unsigned>::iterator i = vec.begin();
449 OrdinalVector::const_iterator ip = parts.begin() ;
451 for ( ; i != vec.end() && ip != parts.end() ; ++i ) {
453 const unsigned ord = *ip;
456 if ( ord < *i ) { i = vec.insert( i , ord ); }
462 for ( ; ip != parts.end() ; ++ip ) {
463 vec.push_back( *ip );
473 void BulkData::internal_change_entity_parts(
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);
483 Bucket *
const k_old = m_entity_repo.get_entity_bucket( entity );
485 const unsigned i_old = entity.bucket_ordinal() ;
487 if ( k_old && k_old->member_all( add_parts ) &&
488 ! k_old->member_any( remove_parts ) ) {
497 OrdinalVector parts_total ;
508 const std::pair<const unsigned *, const unsigned*>
509 bucket_parts = k_old->superset_part_ordinals();
511 const unsigned * parts_begin = bucket_parts.first;
512 const unsigned * parts_end = bucket_parts.second;
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);
518 if ( !remove_parts.empty() ) {
519 parts_removed.reserve(remove_parts.size());
520 filter_out( parts_total , remove_parts , parts_removed );
524 parts_total.reserve(add_parts.size());
527 if ( !add_parts.empty() ) {
528 merge_in( parts_total , add_parts );
531 if ( parts_total.empty() ) {
533 const unsigned univ_ord =
534 m_mesh_meta_data.universal_part().mesh_meta_data_ordinal();
535 parts_total.push_back( univ_ord );
542 m_bucket_repository.declare_bucket(
543 entity.entity_rank(),
546 m_mesh_meta_data.get_fields()
552 m_bucket_repository.copy_fields( *k_new , k_new->size() , *k_old , i_old );
555 m_bucket_repository.initialize_fields( *k_new , k_new->size() );
559 m_entity_repo.change_entity_bucket( *k_new, entity, k_new->size() );
560 m_bucket_repository.add_entity_to_bucket( entity, *k_new );
563 if ( k_old && k_old->capacity() > 0) { m_bucket_repository.remove_entity( k_old , i_old ); }
566 m_entity_repo.set_entity_sync_count( entity, m_sync_count );
570 internal_propagate_part_changes( entity , parts_removed );
577 void BulkData::internal_change_entity_parts(
579 const OrdinalVector & add_parts ,
580 const OrdinalVector & remove_parts,
581 bool always_propagate_internal_changes )
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);
588 Bucket *
const k_old = m_entity_repo.get_entity_bucket( entity );
590 const unsigned i_old = entity.bucket_ordinal() ;
592 if ( k_old && k_old->member_all( add_parts ) &&
593 ! k_old->member_any( remove_parts ) ) {
600 OrdinalVector parts_removed ;
602 OrdinalVector parts_total ;
613 const std::pair<const unsigned *, const unsigned*>
614 bucket_parts = k_old->superset_part_ordinals();
616 const unsigned * parts_begin = bucket_parts.first;
617 const unsigned * parts_end = bucket_parts.second;
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);
623 if ( !remove_parts.empty() ) {
624 parts_removed.reserve(remove_parts.size());
625 filter_out( parts_total , remove_parts , parts_removed );
629 parts_total.reserve(add_parts.size());
632 if ( !add_parts.empty() ) {
633 merge_in( parts_total , add_parts );
636 if ( parts_total.empty() ) {
638 const unsigned univ_ord =
639 m_mesh_meta_data.universal_part().mesh_meta_data_ordinal();
640 parts_total.push_back( univ_ord );
647 m_bucket_repository.declare_bucket(
648 entity.entity_rank(),
651 m_mesh_meta_data.get_fields()
657 m_bucket_repository.copy_fields( *k_new , k_new->size() , *k_old , i_old );
660 m_bucket_repository.initialize_fields( *k_new , k_new->size() );
664 m_entity_repo.change_entity_bucket( *k_new, entity, k_new->size() );
665 m_bucket_repository.add_entity_to_bucket( entity, *k_new );
668 if ( k_old && k_old->capacity() > 0) { m_bucket_repository.remove_entity( k_old , i_old ); }
671 m_entity_repo.set_entity_sync_count( entity, m_sync_count );
677 const PartVector& all_parts = m_mesh_meta_data.get_parts();
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);
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 );
700 Entity & entity = *entity_in ;
702 TraceIfWatching(
"stk_classic::mesh::BulkData::destroy_entity", LOG_ENTITY, entity.key());
703 DiagIfWatching(LOG_ENTITY, entity.key(),
"entity state: " << entity);
705 require_ok_to_modify( );
707 bool has_upward_relation = false ;
710 irel = entity.relations() ;
711 ! irel.empty() && ! has_upward_relation ; ++irel ) {
713 has_upward_relation = entity.entity_rank() <= irel->entity_rank();
716 if ( has_upward_relation ) {
return false ; }
718 if ( EntityLogDeleted == entity.log_query() ) {
734 while ( ! entity.relations().empty() ) {
736 * entity.relations().back().entity(),
737 entity.relations().back().identifier());
744 Bucket& orig_bucket = entity.bucket();
745 unsigned orig_bucket_ordinal = entity.bucket_ordinal();
755 m_entity_repo.destroy_later( entity, m_bucket_repository.get_nil_bucket() );
757 m_bucket_repository.remove_entity( &orig_bucket , orig_bucket_ordinal );
774 std::vector<Entity *>& requested_entities)
776 Trace_(
"stk_classic::mesh::BulkData::generate_new_entities");
778 typedef stk_classic::parallel::DistributedIndex::KeyType KeyType;
779 std::vector< std::vector<KeyType> >
781 m_entities_index.generate_new_keys(requests, requested_key_types);
784 Part *
const owns = & m_mesh_meta_data.locally_owned_part();
786 std::vector<Part*> rem ;
787 std::vector<Part*> add;
788 add.push_back( owns );
790 requested_entities.clear();
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) {
799 requested_entities.reserve(cnt);
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) {
806 std::pair<Entity *, bool> result = m_entity_repo.internal_create_entity(key);
812 ThrowErrorMsgIf( ! result.second,
813 "Generated " << print_entity_key(m_mesh_meta_data, key) <<
814 " which was already used in this modification cycle.");
818 Entity* new_entity = result.first;
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);
825 requested_entities.push_back(new_entity);