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);
void verify_parallel_consistency(const MetaData &s, ParallelMachine pm)
Verify that the meta data is identical on all processors.
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's field data.
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...
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.
unsigned parallel_machine_rank(ParallelMachine parallel_machine)
Member function parallel_machine_rank ...
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...
unsigned parallel_size() const
Size of the parallel machine.
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.
unsigned parallel_machine_size(ParallelMachine parallel_machine)
Member function parallel_machine_size ...
A fundamental unit within the discretization of a problem domain, including but not limited to nodes...
void supersets(PartVector &) const
This bucket is a subset of these parts.
void parallel_machine_barrier(ParallelMachine parallel_machine)
Member function parallel_machine_barrier ...
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.
std::vector< Part *> PartVector
Collections of parts are frequently maintained as a vector of Part pointers.
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.
A container for the field data of a homogeneous collection of entities.
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.