예제 #1
0
void BulkData::destroy_relation( Entity & e1 , Entity & e2 , unsigned kind )
{
  // When removing a relationship may need to
  // remove part membership and set field relation pointer to NULL

  PartSet del ;
  bool to_e1 = false ;

  std::vector<Relation>::iterator i ;

  for ( i = e1.m_relation.end() ; i != e1.m_relation.begin() ; ) {
    --i ;
    if ( i->entity() == & e2 && i->kind() == kind ) {
      if ( i->forward() ) {
        clear_field_relations( e1 , i->entity_type() ,
                                    i->identifier() ,
                                    i->kind() );
        deduce_part_relations( e1, e2, i->identifier(), i->kind(), del );
      }
      i = e1.m_relation.erase( i );
    }
  }

  for ( i = e2.m_relation.end() ; i != e2.m_relation.begin() ; ) {
    --i ;
    if ( i->entity() == & e1 && i->kind() == kind ) {
      if ( i->forward() ) {
        clear_field_relations( e2 , i->entity_type() ,
                                    i->identifier() ,
                                    i->kind() );
        deduce_part_relations( e2, e1, i->identifier(), i->kind(), del );
        to_e1 = true ;
      }
      i = e2.m_relation.erase( i );
    }
  }

  Entity & e_to = to_e1 ? e1 : e2 ;

  {
    PartSet keep ;

    deduce_part_relations( e_to , keep );

    if ( ! keep.empty() ) {
      // Eliminate the 'keep' from the accumulated 'del'

      for ( PartSet::iterator j = del.end() ; j != del.begin() ; ) {
        --j ;
        if ( contain( keep , **j ) ) { j = del.erase( j ); }
      }
    }
  }

  if ( ! del.empty() ) {
    PartSet add ;
    internal_change_entity_parts( e_to , add , del );
  }
}
예제 #2
0
void BulkData::declare_relation( Entity & e_from ,
                                     Entity & e_to ,
                                     const unsigned identifier ,
                                     const unsigned kind )
{
  static const char method[] = "phdmesh::BulkData::declare_relation" ;

  if ( in_closure( e_to , e_from ) ) {
    std::ostringstream msg ;
    print_declare_relation( msg , method , e_from , e_to , identifier , kind );
    msg << " FAILED DUE TO CIRCULAR CLOSURE." ;
    throw std::runtime_error( msg.str() );
  }

  {
    const Relation forward( e_to , identifier , kind , false );
    const std::vector<Relation>::iterator e = e_from.m_relation.end();
          std::vector<Relation>::iterator i = e_from.m_relation.begin();

    i = std::lower_bound( i , e , forward , LessRelation() );

    if ( e == i || forward != *i ) { // Not a duplicate

      if ( e != i && forward.attribute() == i->attribute() ) {
        std::ostringstream msg ;
        print_declare_relation( msg, method, e_from, e_to, identifier, kind );
        msg << " FAILED, ALREADY HAS THIS RELATION TO " ;
        print_entity_key( msg , i->entity()->key() );
        throw std::runtime_error(msg.str());
      }

      e_from.m_relation.insert( i , forward );
    }
  }

  {
    const Relation converse( e_from , identifier , kind , true );
    const std::vector<Relation>::iterator e = e_to.m_relation.end();
          std::vector<Relation>::iterator i = e_to.m_relation.begin();

    i = std::lower_bound( i , e , converse , LessRelation() );

    if ( e == i || converse != *i ) { // Not a duplicate
      e_to.m_relation.insert( i , converse );
    }
  }

  {
    PartSet add , del ;

    deduce_part_relations( e_from , e_to , identifier , kind , add );

    internal_change_entity_parts( e_to , add , del );
  }

  set_field_relations( e_from , e_to , identifier , kind );
}
예제 #3
0
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);

}
예제 #4
0
void BulkData::declare_relation( Entity & e_from ,
                                 Entity & e_to ,
                                 const unsigned local_id )
{
  static const char method[] = "stk::mesh::BulkData::declare_relation" ;

  assert_ok_to_modify( method );

  assert_valid_relation( method , *this , e_from , e_to );

  m_entity_repo.declare_relation( e_from, e_to, local_id, m_sync_count);


  PartVector add , empty ;

  // Deduce and set new part memberships:

  induced_part_membership( e_from, empty,
      e_to.entity_rank(), local_id, add );

  internal_change_entity_parts( e_to , add , empty );

  set_field_relations( e_from , e_to , local_id );
}
예제 #5
0
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 );
    }
  }
}
예제 #6
0
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 );
    }
  }
}
예제 #7
0
void BulkData::change_entity_owner( const std::vector<EntityProc> & arg_change )
{
  static const char method[] = "stk::mesh::BulkData::change_entity_owner" ;

  const MetaData  & meta = m_mesh_meta_data ;
  const unsigned  p_rank = m_parallel_rank ;
  const unsigned  p_size = m_parallel_size ;
  ParallelMachine p_comm = m_parallel_machine ;

  //------------------------------
  // Verify the input changes, generate a clean local change list, and
  // generate the remote change list so that all processes know about
  // pending changes.

  std::vector<EntityProc> local_change( arg_change );

  // Parallel synchronous clean up and verify the requested changes:
  clean_and_verify_parallel_change( method , *this , local_change );

  //----------------------------------------
  // Parallel synchronous determination of changing
  // shared and ghosted.

  std::vector<EntityProc> ghosted_change ;
  std::vector<EntityProc> shared_change ;

  generate_parallel_change( *this , local_change ,
                            shared_change , ghosted_change );

  //------------------------------
  // Have enough information to delete all effected ghosts.
  // If the closure of a ghost contains a changing entity
  // then that ghost must be deleted.
  // Request that all ghost entities in the closure of the ghost be deleted.

  typedef std::set<EntityProc,EntityLess> EntityProcSet;
  typedef std::set<Entity*,EntityLess> EntitySet;

  // Closure of the owner change for impacted ghost entities.

  EntityProcSet send_closure ;

  for ( std::vector<EntityProc>::iterator
        i = local_change.begin() ; i != local_change.end() ; ++i ) {
    insert_closure_send( *i , send_closure );
  }

  {
    EntitySet work ;

    for ( std::vector<EntityProc>::const_iterator
          i = ghosted_change.begin() ; i != ghosted_change.end() ; ++i ) {
      insert_transitive_ghost( i->first , m_parallel_rank , work );
    }

    for ( std::vector<EntityProc>::const_iterator
          i = shared_change.begin() ; i != shared_change.end() ; ++i ) {
      insert_transitive_ghost( i->first , m_parallel_rank , work );
    }

    for ( EntityProcSet::iterator
          i = send_closure.begin() ; i != send_closure.end() ; ++i ) {
      insert_transitive_ghost( i->first , m_parallel_rank , work );
    }

    // The ghosted change list will become invalid
    ghosted_change.clear();

    std::vector<EntityProc> empty ;
    std::vector<Entity*> effected_ghosts( work.begin() , work.end() );

    // Skip 'm_ghosting[0]' which is the shared subset.
    for ( std::vector<Ghosting*>::iterator
          ig = m_ghosting.begin() + 1 ; ig != m_ghosting.end() ; ++ig ) {
      // parallel synchronous:
      internal_change_ghosting( **ig , empty , effected_ghosts );
    }
  }

  //------------------------------
  // Consistently change the owner on all processes.
  // 1) The local_change list is giving away ownership.
  // 2) The shared_change may or may not be receiving ownership

  {
    PartVector owned( 1 );
    owned[0] = & meta.locally_owned_part();

    for ( std::vector<EntityProc>::iterator
          i = local_change.begin() ; i != local_change.end() ; ++i ) {
      // Giving ownership, change the parts first and then
      // the owner rank to pass the ownership test.
      change_entity_parts( * i->first , PartVector() , owned );

      m_entity_repo.set_entity_owner_rank( *(i->first), i->second);
    }

    for ( std::vector<EntityProc>::iterator
          i = shared_change.begin() ; i != shared_change.end() ; ++i ) {
      m_entity_repo.set_entity_owner_rank( *(i->first), i->second);
      if ( p_rank == i->second ) { // I receive ownership
        change_entity_parts( * i->first , owned , PartVector() );
      }
    }
  }

  //------------------------------
  // Send entities, along with their closure, to the new owner processes
  {
    std::ostringstream error_msg ;
    int error_count = 0 ;

    CommAll comm( p_comm );

    for ( std::set<EntityProc,EntityLess>::iterator
          i = send_closure.begin() ; i != send_closure.end() ; ++i ) {
      CommBuffer & buffer = comm.send_buffer( i->second );
      Entity     & entity = * i->first ;
      pack_entity_info( buffer , entity );
      pack_field_values( buffer , entity );
    }

    comm.allocate_buffers( p_size / 4 );

    for ( std::set<EntityProc,EntityLess>::iterator
          i = send_closure.begin() ; i != send_closure.end() ; ++i ) {
      CommBuffer & buffer = comm.send_buffer( i->second );
      Entity     & entity = * i->first ;
      pack_entity_info( buffer , entity );
      pack_field_values( buffer , entity );
    }

    comm.communicate();

    for ( unsigned p = 0 ; p < p_size ; ++p ) {
      CommBuffer & buf = comm.recv_buffer(p);
      while ( buf.remaining() ) {
        PartVector parts ;
        std::vector<Relation> relations ;
        EntityKey key ;
        unsigned  owner = ~0u ;

        unpack_entity_info( buf, *this, key, owner, parts, relations );

        // Received entity information will be correct,
        // modulo the owned and shared parts

        remove( parts , meta.globally_shared_part() );

        if ( owner == p_rank ) {
          // Must have the locally_owned_part
          insert( parts , meta.locally_owned_part() );
        }
        else {
          // Must not have the locally_owned_part
          remove( parts , meta.locally_owned_part() );
        }

        std::pair<Entity*,bool> result =
          m_entity_repo.internal_create_entity( key );

        m_entity_repo.log_created_parallel_copy( *(result.first) );

        // The entity was copied and not created.

        m_entity_repo.set_entity_owner_rank( *(result.first), owner);

        internal_change_entity_parts( *result.first , parts , PartVector() );

        declare_relation( *result.first , relations );

        if ( ! unpack_field_values( buf , * result.first , error_msg ) ) {
          ++error_count ;
        }
      }
    }

    all_reduce( p_comm , ReduceSum<1>( & error_count ) );

    if ( error_count ) { throw std::runtime_error( error_msg.str() ); }

    // Any entity that I sent and is not in an owned closure is deleted.
    // The owned closure will be effected by received entities, so can
    // only clean up after the newly owned entities have been received.
    // Destroy backwards so as not to invalidate closures in the process.

    {
      Entity * entity = NULL ;

      for ( std::set<EntityProc,EntityLess>::iterator
            i = send_closure.end() ; i != send_closure.begin() ; ) {

        Entity * e = (--i)->first ;

        // The same entity may be sent to more than one process.
        // Only evaluate it once.

        if ( entity != e ) {
          entity = e ;
          if ( ! member_of_owned_closure( *e , p_rank ) ) {
            if ( ! destroy_entity( e ) ) {
              throw std::logic_error(std::string("BulkData::destroy_entity FAILED"));
            }
          }
        }
      }
    }

    send_closure.clear(); // Has been invalidated
  }
}