void printNode(std::ostringstream& msg, Entity *node) { printEntity(msg, node); PairIterRelation rels = node->relations(); for (unsigned i = 0; i < rels.size(); i++) { Entity *entity = rels[i].entity(); if (entity->entity_rank() > node->entity_rank()) printEntity(msg, entity); } }
bool in_closure( const Entity & e_from , const Entity & e ) { PairIterRelation rel = e_from.relations(); bool not_in_closure = & e_from != & e ; for ( ; not_in_closure && rel ; ++rel ) { if ( rel->forward() ) { not_in_closure = ! in_closure( * rel->entity() , e ); } } return ! not_in_closure ; }
void closure( const Entity & e_from , std::vector<Entity*> & eset ) { PairIterRelation rel = e_from.relations(); for ( ; rel ; ++rel ) { if ( rel->forward() ) { Entity * const e = rel->entity(); std::vector<Entity*>::iterator i = eset.begin(); std::vector<Entity*>::iterator j = eset.end(); i = std::lower_bound( i , j , e , LessEntityPointer() ); if ( i == j || e != *i ) { eset.push_back( e ); closure( *e , eset ); } } } }
/** \brief Is in owned closure of the given process, * typically the local process. */ bool in_owned_closure( const Entity & entity , unsigned proc ) { // TODO: This function has a potential performance problem if relations // are dense. // Does proc own this entity? If so, we're done bool result = entity.owner_rank() == proc ; if ( ! result ) { const unsigned erank = entity.entity_rank(); // Does entity have an upward relation to an entity owned by proc for ( PairIterRelation rel = entity.relations(); ! result && ! rel.empty() ; ++rel ) { result = erank < rel->entity_rank() && in_owned_closure( * rel->entity(), proc); } } return result ; }
bool gather_field_data( const field_type & field , const Entity & entity , typename FieldTraits< field_type >::data_type * dst ) { typedef typename FieldTraits< field_type >::data_type T ; PairIterRelation rel = entity.relations( EType ); bool result = NRel == (unsigned) rel.size(); if ( result ) { T * const dst_end = dst + NType * NRel ; for ( const T * src ; ( dst < dst_end ) && ( src = field_data( field , * rel->entity() ) ) ; ++rel , dst += NType ) { Copy<NType>( dst , src ); } result = dst == dst_end ; } return result ; }
void pack_entity_info( CommBuffer & buf , const Entity & entity ) { const EntityKey & key = entity.key(); const unsigned owner = entity.owner_rank(); const std::pair<const unsigned *, const unsigned *> part_ordinals = entity.bucket().superset_part_ordinals(); const PairIterRelation relations = entity.relations(); const unsigned nparts = part_ordinals.second - part_ordinals.first ; const unsigned nrel = relations.size(); buf.pack<EntityKey>( key ); buf.pack<unsigned>( owner ); buf.pack<unsigned>( nparts ); buf.pack<unsigned>( part_ordinals.first , nparts ); buf.pack<unsigned>( nrel ); for ( unsigned i = 0 ; i < nrel ; ++i ) { buf.pack<EntityKey>( relations[i].entity()->key() ); buf.pack<unsigned>( relations[i].identifier() ); buf.pack<unsigned>( relations[i].attribute() ); } }
void BulkData::internal_propagate_relocation( Entity & entity ) { PairIterRelation rel = entity.relations(); for ( ; rel ; ++rel ) { if ( rel->forward() ) { Entity & e_to = * rel->entity(); set_field_relations( entity, e_to, rel->identifier(), rel->kind() ); } else { Entity & e_from = * rel->entity(); set_field_relations( e_from, entity, rel->identifier(), rel->kind() ); } } }
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 ); } } }
void BulkData::internal_propagate_part_changes( Entity & entity , const PartSet & removed ) { const EntityType etype = entity.entity_type(); Part * const owns_part = & m_mesh_meta_data.locally_owned_part(); Part * const uses_part = & m_mesh_meta_data.locally_used_part(); PairIterRelation rel = entity.relations(); for ( ; rel ; ++rel ) { const unsigned rel_ident = rel->identifier(); const unsigned rel_kind = rel->kind(); if ( rel->forward() ) { Entity & e_to = * rel->entity(); PartSet to_del ; PartSet to_add ; if ( ! removed.empty() ) { const EntityType t_to = e_to.entity_type(); // 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' deduce_part_relations( e_to , to_add ); to_del.reserve( removed.size() ); for ( PartSet::const_iterator j = removed.begin() ; j != removed.end() ; ++j ) { Part * const p = *j ; if ( p != owns_part && p != uses_part && ! contain( to_add , *p ) ) { to_del.push_back( p ); // What if removing a part with a part-relation ? const std::vector<PartRelation> & part_rel = m_mesh_meta_data.get_part_relations(); for ( std::vector<PartRelation>::const_iterator k = part_rel.begin() ; k != part_rel.end() ; ++k ) { const PartRelation & stencil = *k ; if ( p == stencil.m_root && 0 <= (*stencil.m_function)(etype,t_to,rel_ident,rel_kind) && ! contain( to_add , * stencil.m_target ) ) { } } } } } else { deduce_part_relations( entity , e_to , rel_ident , rel_kind , to_add ); } internal_change_entity_parts( e_to , to_add , to_del ); set_field_relations( entity, e_to, rel_ident , rel_kind ); } else { Entity & e_from = * rel->entity(); set_field_relations( e_from, entity, rel_ident, rel_kind ); } } }
bool BulkData::destroy_entity( Entity * & entity_in ) { Entity & entity = *entity_in ; TraceIfWatching("stk_classic::mesh::BulkData::destroy_entity", LOG_ENTITY, entity.key()); DiagIfWatching(LOG_ENTITY, entity.key(), "entity state: " << entity); require_ok_to_modify( ); bool has_upward_relation = false ; for ( PairIterRelation irel = entity.relations() ; ! irel.empty() && ! has_upward_relation ; ++irel ) { has_upward_relation = entity.entity_rank() <= irel->entity_rank(); } if ( has_upward_relation ) { return false ; } if ( EntityLogDeleted == entity.log_query() ) { // Cannot already be destroyed. return false ; } //------------------------------ // Immediately remove it from relations and buckets. // Postpone deletion until modification_end to be sure that // 1) No attempt is made to re-create it. // 2) Parallel index is cleaned up. // 3) Parallel sharing is cleaned up. // 4) Parallel ghosting is cleaned up. // // Must clean up the parallel lists before fully deleting the entity. // It is important that relations be destroyed in reverse order so that // the higher (back) relations are destroyed first. while ( ! entity.relations().empty() ) { destroy_relation( entity , * entity.relations().back().entity(), entity.relations().back().identifier()); } // We need to save these items and call remove_entity AFTER the call to // destroy_later because remove_entity may destroy the bucket // which would cause problems in m_entity_repo.destroy_later because it // makes references to the entity's original bucket. Bucket& orig_bucket = entity.bucket(); unsigned orig_bucket_ordinal = entity.bucket_ordinal(); // Set the bucket to 'bucket_nil' which: // 1) has no parts at all // 2) has no field data // 3) has zero capacity // // This keeps the entity-bucket methods from catastrophically failing // with a bad bucket pointer. m_entity_repo.destroy_later( entity, m_bucket_repository.get_nil_bucket() ); m_bucket_repository.remove_entity( &orig_bucket , orig_bucket_ordinal ); // Add destroyed entity to the transaction // m_transaction_log.delete_entity ( *entity_in ); // Set the calling entity-pointer to NULL; // hopefully the user-code will clean up any outstanding // references to this entity. entity_in = NULL ; return true ; }