void BulkData::destroy_relation( Entity & e_from , Entity & e_to ) { static const char method[]= "stk::mesh::BulkData::destroy_relation" ; assert_ok_to_modify( method ); assert_valid_relation( method , *this , e_from , e_to ); //------------------------------ // When removing a relationship may need to // remove part membership and set field relation pointer to NULL PartVector del , keep ; for ( PairIterRelation i = e_to.relations() ; i.first != i.second ; ++(i.first) ) { if ( !( i.first->entity() == & e_from ) && ( e_to.entity_rank() < i.first->entity_rank() ) ) { induced_part_membership( * i.first->entity(), del, e_to.entity_rank(), i.first->identifier(), keep ); } } for ( PairIterRelation i = e_from.relations() ; i.first != i.second ; ++(i.first) ) { if ( i.first->entity() == & e_to ) { induced_part_membership( e_from, keep, e_to.entity_rank(), i.first->identifier(), del ); clear_field_relations( e_from , e_to.entity_rank() , i.first->identifier() ); } } //------------------------------ // 'keep' contains the parts deduced from kept relations // 'del' contains the parts deduced from deleted relations // that are not in 'keep' // Only remove these part memberships the entity is not shared. // If the entity is shared then wait until modificaton_end_synchronize. //------------------------------ if ( ! del.empty() && (parallel_size() < 2 || e_to.sharing().empty()) ) { PartVector add ; internal_change_entity_parts( e_to , add , del ); } //delete relations from the entities m_entity_repo.destroy_relation( e_from, e_to); }
bool has_superset( const Bucket & bucket , const PartVector & ps ) { const std::pair<const unsigned *, const unsigned *> part_ord = bucket.superset_part_ordinals(); bool result = ! ps.empty(); for ( PartVector::const_iterator i = ps.begin() ; result && i != ps.end() ; ++i ) { const unsigned ordinal = (*i)->mesh_meta_data_ordinal(); const unsigned * iter = std::lower_bound( part_ord.first , part_ord.second , ordinal ); result = iter < part_ord.second && ordinal == *iter ; } return result ; }
bool contain( const PartVector & super , const PartVector & sub ) { bool result = ( ! sub.empty() ) && ( sub.size() <= super.size() ); if ( result ) { PartLess comp ; const PartVector::const_iterator ev = super.end(); PartVector::const_iterator iv = super.begin(); const PartVector::const_iterator ep = sub.end(); PartVector::const_iterator ip = sub.begin(); while ( result && ip != ep ) { Part * const q = *ip ; ++ip ; iv = std::lower_bound( iv , ev , q , comp ); result = iv != ev && *iv == q ; } } return result ; }
void BulkData::internal_propagate_part_changes( Entity & entity , const PartVector & removed ) { const unsigned etype = entity.entity_rank(); PairIterRelation rel = entity.relations(); for ( ; ! rel.empty() ; ++rel ) { const unsigned rel_type = rel->entity_rank(); const unsigned rel_ident = rel->identifier(); if ( rel_type < etype ) { // a 'to' entity Entity & e_to = * rel->entity(); PartVector to_del , to_add , empty ; // Induce part membership from this relationship to // pick up any additions. induced_part_membership( entity, empty, rel_type, rel_ident, to_add ); if ( ! removed.empty() ) { // Something was removed from the 'from' entity, // deduce what may have to be removed from the 'to' entity. // Deduce parts for 'e_to' from all upward relations. // Any non-parallel part that I removed that is not deduced for // 'e_to' must be removed from 'e_to' for ( PairIterRelation to_rel = e_to.relations(); ! to_rel.empty() ; ++to_rel ) { if ( e_to.entity_rank() < to_rel->entity_rank() && & entity != to_rel->entity() /* Already did this entity */ ) { // Relation from to_rel->entity() to e_to induced_part_membership( * to_rel->entity(), empty, e_to.entity_rank(), to_rel->identifier(), to_add ); } } for ( PartVector::const_iterator j = removed.begin() ; j != removed.end() ; ++j ) { if ( ! contain( to_add , **j ) ) { induced_part_membership( **j, etype, rel_type, rel_ident, to_del ); } } } if ( parallel_size() < 2 || e_to.sharing().empty() ) { // Entirely local, ok to remove memberships now internal_change_entity_parts( e_to , to_add , to_del ); } else { // Shared, do not remove memberships now. // Wait until modification_end. internal_change_entity_parts( e_to , to_add , empty ); } set_field_relations( entity, e_to, rel_ident ); } else if ( etype < rel_type ) { // a 'from' entity Entity & e_from = * rel->entity(); set_field_relations( e_from, entity, rel_ident ); } } }
Entity declare_element_to_entity(BulkData & mesh, Entity elem, Entity entity, const unsigned relationOrdinal, const PartVector& parts, stk::topology entity_top) { stk::topology elem_top = mesh.bucket(elem).topology(); std::vector<unsigned> entity_node_ordinals(entity_top.num_nodes()); elem_top.sub_topology_node_ordinals(mesh.entity_rank(entity), relationOrdinal, entity_node_ordinals.begin()); const stk::mesh::Entity *elem_nodes = mesh.begin_nodes(elem); EntityVector entity_top_nodes(entity_top.num_nodes()); elem_top.sub_topology_nodes(elem_nodes, mesh.entity_rank(entity), relationOrdinal, entity_top_nodes.begin()); Permutation perm = mesh.find_permutation(elem_top, elem_nodes, entity_top, &entity_top_nodes[0], relationOrdinal); OrdinalVector ordinal_scratch; ordinal_scratch.reserve(64); PartVector part_scratch; part_scratch.reserve(64); if(!parts.empty()) { mesh.change_entity_parts(entity, parts); } const stk::mesh::ConnectivityOrdinal *side_ordinals = mesh.begin_ordinals(elem, mesh.entity_rank(entity)); unsigned num_sides = mesh.count_valid_connectivity(elem, mesh.entity_rank(entity)); bool elem_to_side_exists = false; for(unsigned i = 0; i < num_sides; ++i) { if(side_ordinals[i] == relationOrdinal) { elem_to_side_exists = true; break; } } if(!elem_to_side_exists) { mesh.declare_relation(elem, entity, relationOrdinal, perm, ordinal_scratch, part_scratch); } const unsigned num_side_nodes = mesh.count_valid_connectivity(entity, stk::topology::NODE_RANK); if(0 == num_side_nodes) { Permutation node_perm = stk::mesh::Permutation::INVALID_PERMUTATION; Entity const *elem_nodes_local = mesh.begin_nodes(elem); for(unsigned i = 0; i < entity_top.num_nodes(); ++i) { Entity node = elem_nodes_local[entity_node_ordinals[i]]; mesh.declare_relation(entity, node, i, node_perm, ordinal_scratch, part_scratch); } } else { ThrowAssertMsg(num_side_nodes == entity_top.num_nodes(), "declare_element_to_entity: " << mesh.entity_key(entity) << " already exists with different number of nodes."); } return entity; }
void BulkData::internal_change_entity_parts( Entity & entity , const PartVector & add_parts , const PartVector & remove_parts ) { TraceIfWatching("stk_classic::mesh::BulkData::internal_change_entity_parts", LOG_ENTITY, entity.key()); DiagIfWatching(LOG_ENTITY, entity.key(), "entity state: " << entity); DiagIfWatching(LOG_ENTITY, entity.key(), "add_parts: " << add_parts); DiagIfWatching(LOG_ENTITY, entity.key(), "remove_parts: " << remove_parts); Bucket * const k_old = m_entity_repo.get_entity_bucket( entity ); const unsigned i_old = entity.bucket_ordinal() ; if ( k_old && k_old->member_all( add_parts ) && ! k_old->member_any( remove_parts ) ) { // Is already a member of all add_parts, // is not a member of any remove_parts, // thus nothing to do. return ; } PartVector parts_removed ; OrdinalVector parts_total ; // The final part list //-------------------------------- if ( k_old ) { // Keep any of the existing bucket's parts // that are not a remove part. // This will include the 'intersection' parts. // // These parts are properly ordered and unique. const std::pair<const unsigned *, const unsigned*> bucket_parts = k_old->superset_part_ordinals(); const unsigned * parts_begin = bucket_parts.first; const unsigned * parts_end = bucket_parts.second; const unsigned num_bucket_parts = parts_end - parts_begin; parts_total.reserve( num_bucket_parts + add_parts.size() ); parts_total.insert( parts_total.begin(), parts_begin , parts_end); if ( !remove_parts.empty() ) { parts_removed.reserve(remove_parts.size()); filter_out( parts_total , remove_parts , parts_removed ); } } else { parts_total.reserve(add_parts.size()); } if ( !add_parts.empty() ) { merge_in( parts_total , add_parts ); } if ( parts_total.empty() ) { // Always a member of the universal part. const unsigned univ_ord = m_mesh_meta_data.universal_part().mesh_meta_data_ordinal(); parts_total.push_back( univ_ord ); } //-------------------------------- // Move the entity to the new bucket. Bucket * k_new = m_bucket_repository.declare_bucket( entity.entity_rank(), parts_total.size(), & parts_total[0] , m_mesh_meta_data.get_fields() ); // If changing buckets then copy its field values from old to new bucket if ( k_old ) { m_bucket_repository.copy_fields( *k_new , k_new->size() , *k_old , i_old ); } else { m_bucket_repository.initialize_fields( *k_new , k_new->size() ); } // Set the new bucket m_entity_repo.change_entity_bucket( *k_new, entity, k_new->size() ); m_bucket_repository.add_entity_to_bucket( entity, *k_new ); // If changing buckets then remove the entity from the bucket, if ( k_old && k_old->capacity() > 0) { m_bucket_repository.remove_entity( k_old , i_old ); } // Update the change counter to the current cycle. m_entity_repo.set_entity_sync_count( entity, m_sync_count ); // Propagate part changes through the entity's relations. internal_propagate_part_changes( entity , parts_removed ); #ifndef NDEBUG //ensure_part_superset_consistency( entity ); #endif }