moab
moab::HigherOrderFactory Class Reference

Functions for converting to/from higher-order elements. More...

#include <HigherOrderFactory.hpp>

List of all members.

Public Member Functions

 HigherOrderFactory (Core *, Interface::HONodeAddedRemoved *function_object)
 ~HigherOrderFactory ()
ErrorCode convert (const EntityHandle meshset, const bool mid_edge_nodes, const bool mid_face_nodes, const bool mid_volume_nodes)
ErrorCode convert (const Range &entities, const bool mid_edge_nodes, const bool mid_face_nodes, const bool mid_volume_nodes)

Public Attributes

unsigned char mNodeMap [MBMAXTYPE][8][8]

Private Member Functions

void initialize_map ()
ErrorCode convert_sequence (ElementSequence *sequence, EntityHandle sequence_subset_start, EntityHandle sequence_subset_end, bool mid_edge_nodes, bool mid_face_nodes, bool mid_volume_nodes)
ErrorCode add_mid_edge_nodes (ElementSequence *)
ErrorCode add_mid_face_nodes (ElementSequence *)
ErrorCode add_mid_volume_nodes (ElementSequence *)
EntityHandle center_node_exist (EntityHandle corner1, EntityHandle corner2, std::vector< EntityHandle > &adj_entities)
EntityHandle center_node_exist (EntityHandle corners[4], std::vector< EntityHandle > &adj_entities)
bool add_center_node (EntityType type, EntityHandle *element_conn, int conn_size, EntityHandle corner_node1, EntityHandle corner_node2, EntityHandle center_node)
 adds a center node to element between corner nodes, returns success
ErrorCode copy_corner_nodes (ElementSequence *src, ElementSequence *dst)
ErrorCode copy_mid_edge_nodes (ElementSequence *src, ElementSequence *dst)
ErrorCode copy_mid_face_nodes (ElementSequence *src, ElementSequence *dst)
ErrorCode copy_mid_volume_nodes (ElementSequence *src, ElementSequence *dst)
ErrorCode copy_nodes (ElementSequence *src, ElementSequence *dst, unsigned nodes_per_elem_to_copy, unsigned src_conn_offset, unsigned dst_conn_offset)
ErrorCode zero_mid_edge_nodes (ElementSequence *dst)
ErrorCode zero_mid_face_nodes (ElementSequence *dst)
ErrorCode zero_mid_volume_nodes (ElementSequence *dst)
ErrorCode zero_nodes (ElementSequence *dst, unsigned nodes_per_elem_to_zero, unsigned dst_conn_offset)
ErrorCode remove_mid_edge_nodes (ElementSequence *seq, EntityHandle start, EntityHandle stop, Tag deletable_ndoes)
ErrorCode remove_mid_face_nodes (ElementSequence *seq, EntityHandle start, EntityHandle stop, Tag deletable_ndoes)
ErrorCode remove_mid_volume_nodes (ElementSequence *seq, EntityHandle start, EntityHandle stop, Tag deletable_ndoes)
ErrorCode remove_ho_nodes (ElementSequence *sequence, EntityHandle subset_start_handle, EntityHandle subset_end_handle, int nodes_per_elem_to_remove, int elem_conn_offset_to_remove, Tag deletable_nodes)
bool tag_for_deletion (EntityHandle element_with_node, int node_index_in_elem_connectivity, ElementSequence *sequence)

Private Attributes

CoremMB
Interface::HONodeAddedRemovedmHONodeAddedRemoved

Detailed Description

Functions for converting to/from higher-order elements.

Authors:
Clinton Stimpson
Date:
11/25/02

Definition at line 38 of file HigherOrderFactory.hpp.


Constructor & Destructor Documentation

Definition at line 39 of file HigherOrderFactory.cpp.

  : mMB(MB), mHONodeAddedRemoved(function_object)
{
  initialize_map();
}

Member Function Documentation

bool moab::HigherOrderFactory::add_center_node ( EntityType  type,
EntityHandle element_conn,
int  conn_size,
EntityHandle  corner_node1,
EntityHandle  corner_node2,
EntityHandle  center_node 
) [private]

adds a center node to element between corner nodes, returns success

Definition at line 633 of file HigherOrderFactory.cpp.

{
  int first_node = std::find(element_conn, element_conn+conn_size, corner_node1) - element_conn;
  int second_node = std::find(element_conn, element_conn+conn_size, corner_node2) - element_conn;
  if(first_node == conn_size || second_node == conn_size)
    assert("We should always find our nodes no matter what" == NULL);
  int high_node_index = mNodeMap[this_type][first_node][second_node];
  element_conn[high_node_index] = center_node;  
  return true;
}

Definition at line 405 of file HigherOrderFactory.cpp.

{
  // for each node, need to see if it was already created.
  EntityType this_type = seq->type();
  SequenceManager* seq_manager = mMB->sequence_manager();

  // offset by number of corner nodes
  int num_vertices = CN::VerticesPerEntity(this_type);
  int num_edges = CN::mConnectivityMap[this_type][0].num_sub_elements;

  const CN::ConnMap& entity_edges = CN::mConnectivityMap[this_type][0];
  
  EntityHandle* element = seq->get_connectivity_array();
  EntityHandle curr_handle = seq->start_handle();
  int nodes_per_element = seq->nodes_per_element();
  EntityHandle* end_element = element + nodes_per_element * (seq->size());

  EntityHandle tmp_edge_conn[2];
  std::vector<EntityHandle> adjacent_entities(32);

  double tmp_coords[3];

  // iterate over the elements
  for(; element < end_element; element+=nodes_per_element)
  {
    // for each edge in this entity
    for(int i=0; i<num_edges; i++)
    {
      // a node was already assigned
      if(element[i+num_vertices] != 0)
        continue;

      tmp_edge_conn[0] = element[entity_edges.conn[i][0]];
      tmp_edge_conn[1] = element[entity_edges.conn[i][1]];

      EntityHandle already_made_node = center_node_exist(tmp_edge_conn[0], tmp_edge_conn[1],
          adjacent_entities);
      
      if(already_made_node)
      {
        element[i+num_vertices] = already_made_node;
      }
      // create a node
      else
      {
        EntitySequence* tmp_sequence = NULL;
        double sum_coords[3] = {0,0,0};
        seq_manager->find(tmp_edge_conn[0], tmp_sequence);
        static_cast<VertexSequence*>(tmp_sequence)->get_coordinates( 
            tmp_edge_conn[0], tmp_coords[0], tmp_coords[1], tmp_coords[2]);
        sum_coords[0] += tmp_coords[0];
        sum_coords[1] += tmp_coords[1];
        sum_coords[2] += tmp_coords[2];
        seq_manager->find(tmp_edge_conn[1], tmp_sequence);
        static_cast<VertexSequence*>(tmp_sequence)->get_coordinates( 
            tmp_edge_conn[1], tmp_coords[0], tmp_coords[1], tmp_coords[2]);
        sum_coords[0] = (sum_coords[0] + tmp_coords[0]) /2;
        sum_coords[1] = (sum_coords[1] + tmp_coords[1]) /2;
        sum_coords[2] = (sum_coords[2] + tmp_coords[2]) /2;

        mMB->create_vertex(sum_coords, element[i+num_vertices]);
      }

      if(mHONodeAddedRemoved)
        mHONodeAddedRemoved->node_added(element[i+num_vertices], curr_handle);
      
    }

    curr_handle++;

  }

  return MB_SUCCESS;
}

Definition at line 324 of file HigherOrderFactory.cpp.

{
  EntityType this_type = seq->type();
  SequenceManager* seq_manager = mMB->sequence_manager();
  int num_vertices = CN::VerticesPerEntity(this_type);
  int num_edges = CN::mConnectivityMap[this_type][0].num_sub_elements;
  num_edges = seq->has_mid_edge_nodes() ? num_edges : 0;
  int num_faces = CN::mConnectivityMap[this_type][1].num_sub_elements;

  const CN::ConnMap& entity_faces = CN::mConnectivityMap[this_type][1];

  EntityHandle* element = seq->get_connectivity_array();
  EntityHandle curr_handle = seq->start_handle();
  int nodes_per_element = seq->nodes_per_element();
  EntityHandle* end_element = element + nodes_per_element * (seq->size());

  EntityHandle tmp_face_conn[4];  // max face nodes = 4
  std::vector<EntityHandle> adjacent_entities(4);

  double tmp_coords[3];
  
  // iterate over the elements
  for(; element < end_element; element+=nodes_per_element)
  {
    // for each edge in this entity
    for(int i=0; i<num_faces; i++)
    {
      // a node was already assigned
      if(element[i+num_edges+num_vertices] != 0)
        continue;

      tmp_face_conn[0] = element[entity_faces.conn[i][0]];
      tmp_face_conn[1] = element[entity_faces.conn[i][1]];
      tmp_face_conn[2] = element[entity_faces.conn[i][2]];
      if(entity_faces.num_corners_per_sub_element[i] == 4)
        tmp_face_conn[3] = element[entity_faces.conn[i][3]];
      else
        tmp_face_conn[3] = 0;

      EntityHandle already_made_node = center_node_exist(tmp_face_conn, adjacent_entities);
      
      if(already_made_node)
      {
        element[i+num_edges+num_vertices] = already_made_node;
      }
      // create a node
      else
      {
        EntitySequence* tmp_sequence = NULL;
        double sum_coords[3] = {0,0,0};
        int max_nodes = entity_faces.num_corners_per_sub_element[i];
        for(int k=0; k<max_nodes; k++)
        {
          seq_manager->find(tmp_face_conn[k], tmp_sequence);
          static_cast<VertexSequence*>(tmp_sequence)->get_coordinates( 
              tmp_face_conn[k], tmp_coords[0], tmp_coords[1], tmp_coords[2]);
          sum_coords[0] += tmp_coords[0];
          sum_coords[1] += tmp_coords[1];
          sum_coords[2] += tmp_coords[2];
        }

        sum_coords[0] /= max_nodes;
        sum_coords[1] /= max_nodes;
        sum_coords[2] /= max_nodes;

        mMB->create_vertex(sum_coords, element[i+num_edges+num_vertices]);
      }

      if(mHONodeAddedRemoved)
        mHONodeAddedRemoved->node_added(element[i+num_edges+num_vertices], curr_handle);
      
    }

    curr_handle++;

  }

  return MB_SUCCESS;
}

Definition at line 272 of file HigherOrderFactory.cpp.

{
  EntityType this_type = seq->type();
  SequenceManager* seq_manager = mMB->sequence_manager();

  // find out where in the connectivity list to add these new mid volume nodes
  int edge_factor = seq->has_mid_edge_nodes() ? 1 : 0;
  int face_factor = seq->has_mid_face_nodes() ? 1 : 0;
  // offset by number of higher order nodes on edges if they exist
  int num_corner_nodes = CN::VerticesPerEntity(this_type);
  int new_node_index = num_corner_nodes;
  new_node_index += edge_factor * CN::mConnectivityMap[this_type][0].num_sub_elements;
  new_node_index += face_factor * CN::mConnectivityMap[this_type][1].num_sub_elements;

  EntityHandle* element = seq->get_connectivity_array();
  EntityHandle curr_handle = seq->start_handle();
  int nodes_per_element = seq->nodes_per_element();
  EntityHandle* end_element = element + nodes_per_element * (seq->size());

  // iterate over the elements
  for(; element < end_element; element+=nodes_per_element)
  {
    // find the centroid of this element
    double tmp_coords[3], sum_coords[3] = {0,0,0};
    EntitySequence* eseq=NULL;
    for(int i=0; i<num_corner_nodes; i++)
    {
      seq_manager->find(element[i], eseq);
      static_cast<VertexSequence*>(eseq)->get_coordinates(
          element[i], tmp_coords[0], tmp_coords[1], tmp_coords[2]
          );
      sum_coords[0] += tmp_coords[0];
      sum_coords[1] += tmp_coords[1];
      sum_coords[2] += tmp_coords[2];
    }
    sum_coords[0] /= num_corner_nodes;
    sum_coords[1] /= num_corner_nodes;
    sum_coords[2] /= num_corner_nodes;

    // create a new vertex at the centroid
    mMB->create_vertex(sum_coords, element[new_node_index]);
    
    if(mHONodeAddedRemoved)
      mHONodeAddedRemoved->node_added(element[new_node_index], curr_handle);

    curr_handle++;
  }

  return MB_SUCCESS;
}
EntityHandle moab::HigherOrderFactory::center_node_exist ( EntityHandle  corner1,
EntityHandle  corner2,
std::vector< EntityHandle > &  adj_entities 
) [private]

returns the handle of the first center node found between the two corner nodes. returns zero if none found entities that share those two corner nodes and have space allocated for mid-edge nodes are returned in a vector

Definition at line 480 of file HigherOrderFactory.cpp.

{
  AEntityFactory* a_fact = mMB->a_entity_factory();
  std::vector<EntityHandle> adj_corner1(32);
  std::vector<EntityHandle> adj_corner2(32);

  // create needed vertex adjacencies
  if (!a_fact->vert_elem_adjacencies())
    a_fact->create_vert_elem_adjacencies();

  // vectors are returned sorted
  
  a_fact->get_adjacencies(corner1, adj_corner1);
  a_fact->get_adjacencies(corner2, adj_corner2);

  // these are the entities adjacent to both nodes
  adj_entities.clear();
  std::set_intersection(adj_corner1.begin(), adj_corner1.end(), adj_corner2.begin(),
      adj_corner2.end(), std::back_inserter<std::vector<EntityHandle> >(adj_entities));


  // iterate of the entities to find a mid node
  const EntityHandle* conn;
  int conn_size = 0;
  for(std::vector<EntityHandle>::iterator iter = adj_entities.begin();
      iter != adj_entities.end(); )
  {
    EntityType this_type = TYPE_FROM_HANDLE(*iter);
    if (this_type == MBENTITYSET) {
      ++iter;
      continue;
    }
    mMB->get_connectivity(*iter, conn, conn_size);
    // if this entity has mid edge nodes
    if(CN::HasMidEdgeNodes(this_type, conn_size))
    {
      // find out at which index the mid node should be at
      int first_node = std::find(conn, conn+conn_size, corner1) - conn;
      int second_node = std::find(conn, conn+conn_size, corner2) - conn;
      if(first_node == conn_size || second_node == conn_size)
        assert("We should always find our nodes no matter what" == NULL);
      int high_node_index = mNodeMap[this_type][first_node][second_node];
      if(conn[high_node_index] != 0)
        return conn[high_node_index];
      ++iter;
    }
    else
    {
      iter = adj_entities.erase(iter);
    }
  }

  return 0;

}
EntityHandle moab::HigherOrderFactory::center_node_exist ( EntityHandle  corners[4],
std::vector< EntityHandle > &  adj_entities 
) [private]

returns the handle of the first center node found between the 3-4 corner nodes. set the last node to zero if you want only 3 nodes returns zero if none found entities that share those corner nodes and have space allocated for mid face nodes are returned in a vector

Definition at line 537 of file HigherOrderFactory.cpp.

{
  AEntityFactory* a_fact = mMB->a_entity_factory();
  std::vector<EntityHandle> adj_corner[4];
  int num_nodes = corners[3] == 0 ? 3 : 4;
  int i = 0;

  // create needed vertex adjacencies
  if (!a_fact->vert_elem_adjacencies())
    a_fact->create_vert_elem_adjacencies();

  // vectors are returned sorted
  for(i=0; i<num_nodes; i++)
    a_fact->get_adjacencies(corners[i], adj_corner[i]);

  // these are the entities adjacent to both nodes
  for(i=1; i<num_nodes; i++)
  {
    adj_entities.clear();
    std::set_intersection(adj_corner[i-1].begin(), adj_corner[i-1].end(), adj_corner[i].begin(),
      adj_corner[i].end(), std::back_inserter<std::vector<EntityHandle> >(adj_entities));
    adj_corner[i].swap(adj_entities);
  }
  adj_entities.swap(adj_corner[i-1]);
  

  // iterate of the entities to find a mid node
  const EntityHandle* conn;
  int conn_size = 0;
  for(std::vector<EntityHandle>::iterator iter = adj_entities.begin();
      iter != adj_entities.end(); )
  {
    EntityType this_type = TYPE_FROM_HANDLE(*iter);
    if (this_type == MBENTITYSET) {
      ++iter;
      continue;
    }
    const CN::ConnMap& entity_faces = CN::mConnectivityMap[this_type][1];
    mMB->get_connectivity(*iter, conn, conn_size);
    int offset = CN::VerticesPerEntity(this_type);
    if(CN::HasMidEdgeNodes(this_type, conn_size))
      offset += CN::mConnectivityMap[this_type][0].num_sub_elements;

    // if this entity has mid face nodes
    if(CN::HasMidFaceNodes(this_type, conn_size))
    {
      int k;
      int indexes[4];
      for(k=0; k<num_nodes; k++)
        indexes[k] = std::find(conn, conn+conn_size, corners[k]) - conn;
      
      // find out at which index the mid node should be at
      for(k=0; k<entity_faces.num_sub_elements; k++)
      {
        if(CN::VerticesPerEntity(entity_faces.target_type[k]) != num_nodes)
          continue;

        int* pivot = std::find(indexes, indexes+num_nodes, entity_faces.conn[k][0]);
        if(pivot == indexes+num_nodes)
          continue;

        if(pivot != indexes)
          std::rotate(indexes, pivot, indexes+num_nodes);

        if(std::equal(indexes, indexes+num_nodes, entity_faces.conn[k]))
        {
          if(conn[k+offset] != 0)
            return conn[k+offset];
          k=entity_faces.num_sub_elements;
        }
        else
        {
          int temp = indexes[1];
          indexes[1] = indexes[num_nodes-1];
          indexes[num_nodes-1] = temp;
          if(std::equal(indexes, indexes+num_nodes, entity_faces.conn[k]))
          {
            if(conn[k+offset] != 0)
              return conn[k+offset];
            k=entity_faces.num_sub_elements;
          }
        }
      }
      ++iter;
    }
    else
    {
      iter = adj_entities.erase(iter);
    }
  }

  return 0;

}
ErrorCode moab::HigherOrderFactory::convert ( const EntityHandle  meshset,
const bool  mid_edge_nodes,
const bool  mid_face_nodes,
const bool  mid_volume_nodes 
)

Definition at line 72 of file HigherOrderFactory.cpp.

{
  Range entities;
  mMB->get_entities_by_handle(meshset, entities, true);
  return convert( entities, mid_edge_nodes, mid_face_nodes, mid_volume_nodes );
}
ErrorCode moab::HigherOrderFactory::convert ( const Range entities,
const bool  mid_edge_nodes,
const bool  mid_face_nodes,
const bool  mid_volume_nodes 
)

Definition at line 82 of file HigherOrderFactory.cpp.

{

  // TODO --  add some more code to prevent from splitting of entity sequences when we don't need to.
  // Say we have all hex8's in our mesh and 3 falses are passed in.  In the end, no conversion will
  // happen, but the sequences could still be split up.

  // find out what entity sequences we need to convert 
  // and where, if necessary, to split them

  SequenceManager* seq_manager = mMB->sequence_manager();
  Range::const_pair_iterator p_iter;
  for (p_iter = entities.const_pair_begin(); p_iter != entities.const_pair_end(); ++p_iter) {
    
    EntityHandle h = p_iter->first;
    while (h <= p_iter->second) {
      
      EntitySequence* seq;
      ErrorCode rval = seq_manager->find( h, seq );
      if (MB_SUCCESS != rval)
        return rval;
      
      if (seq->type() == MBVERTEX || seq->type() >= MBENTITYSET)
        return MB_TYPE_OUT_OF_RANGE;
      
        // make sequence is not structured mesh
      ElementSequence* elemseq = static_cast<ElementSequence*>(seq);
      if (NULL == elemseq->get_connectivity_array())
        return MB_NOT_IMPLEMENTED;
      
      EntityHandle last = p_iter->second;
      if (last > seq->end_handle())
        last = seq->end_handle();
      
      rval = convert_sequence( elemseq, h, last, 
                               mid_edge_nodes,
                               mid_face_nodes,
                               mid_volume_nodes );
      if (MB_SUCCESS != rval)
        return rval;
        
      h = last + 1;
    }
  }
  
  return MB_SUCCESS;
} 
ErrorCode moab::HigherOrderFactory::convert_sequence ( ElementSequence sequence,
EntityHandle  sequence_subset_start,
EntityHandle  sequence_subset_end,
bool  mid_edge_nodes,
bool  mid_face_nodes,
bool  mid_volume_nodes 
) [private]

Definition at line 135 of file HigherOrderFactory.cpp.

{

  ErrorCode status = MB_SUCCESS;

  // lets make sure parameters are ok before we continue
  switch (seq->type()) {
    default: return MB_TYPE_OUT_OF_RANGE; 
    case MBEDGE:
      mid_face_nodes = false;
    case MBTRI:
    case MBQUAD:
      mid_volume_nodes = false;
    case MBTET:
    case MBHEX:
    case MBPRISM:
    case MBPYRAMID:
    case MBKNIFE:
      break;
  }

    // calculate number of nodes in target configuration
  unsigned nodes_per_elem = CN::VerticesPerEntity( seq->type() );
  if (mid_edge_nodes)
    nodes_per_elem += (seq->type() == MBEDGE) ? 1 : CN::NumSubEntities( seq->type(), 1 );
  if (mid_face_nodes)
    nodes_per_elem += (CN::Dimension(seq->type()) == 2) ? 1 : CN::NumSubEntities( seq->type(), 2 );
  if (mid_volume_nodes) 
    nodes_per_elem += 1;
  
  if (nodes_per_elem == seq->nodes_per_element())
    return MB_SUCCESS;
  
  Tag deletable_nodes;
  status = mMB->tag_get_handle(0, 1, MB_TYPE_BIT, deletable_nodes, MB_TAG_CREAT|MB_TAG_BIT);
  if (MB_SUCCESS != status)
    return status;
  
  UnstructuredElemSeq* new_seq = new UnstructuredElemSeq( start,
                                                          end - start + 1,
                                                          nodes_per_elem,
                                                          end - start + 1 );
  
  copy_corner_nodes( seq, new_seq );

  if (seq->has_mid_edge_nodes() && mid_edge_nodes) 
    status = copy_mid_edge_nodes( seq, new_seq );
  else if (seq->has_mid_edge_nodes() && !mid_edge_nodes)
    status = remove_mid_edge_nodes( seq, start, end, deletable_nodes );
  else if (!seq->has_mid_edge_nodes() && mid_edge_nodes)
    status = zero_mid_edge_nodes( new_seq );
  if (MB_SUCCESS != status)
    return status;

  if (seq->has_mid_face_nodes() && mid_face_nodes) 
    status = copy_mid_face_nodes( seq, new_seq );
  else if (seq->has_mid_face_nodes() && !mid_face_nodes)
    status = remove_mid_face_nodes( seq, start, end, deletable_nodes );
  else if (!seq->has_mid_face_nodes() && mid_face_nodes)
    status = zero_mid_face_nodes( new_seq );
  if (MB_SUCCESS != status) {
    mMB->tag_delete( deletable_nodes );
    return status;
  }
 
  if (seq->has_mid_volume_nodes() && mid_volume_nodes) 
    status = copy_mid_volume_nodes( seq, new_seq );
  else if (seq->has_mid_volume_nodes() && !mid_volume_nodes)
    status = remove_mid_volume_nodes( seq, start, end, deletable_nodes );
  else if (!seq->has_mid_volume_nodes() && mid_volume_nodes)
    status = zero_mid_volume_nodes( new_seq );
  if (MB_SUCCESS != status) {
    mMB->tag_delete( deletable_nodes );
    return status;
  }

  // gather nodes that were marked
  Range nodes;
  mMB->get_entities_by_type_and_tag(0, MBVERTEX, &deletable_nodes, NULL, 1, nodes);

  //EntityHandle low_meshset;
  //int dum;
  //low_meshset = CREATE_HANDLE(MBENTITYSET, 0, dum);
  
  for(Range::iterator iter = nodes.begin(); iter != nodes.end(); ++iter)
  {
    unsigned char marked = 0;
    mMB->tag_get_data(deletable_nodes, &(*iter), 1, &marked);
    if(marked)
    {
      // we can delete it
      if(mHONodeAddedRemoved)
        mHONodeAddedRemoved->node_removed( *iter );
      mMB->delete_entities(&(*iter), 1);
    }
  }
  
  const bool create_midedge = !seq->has_mid_edge_nodes() && mid_edge_nodes;
  const bool create_midface = !seq->has_mid_face_nodes() && mid_face_nodes;
  const bool create_midvolm = !seq->has_mid_volume_nodes() && mid_volume_nodes;
  
  mMB->tag_delete(deletable_nodes);

  status = mMB->sequence_manager()->replace_subsequence( new_seq );
  if (MB_SUCCESS != status) {
    SequenceData* data = new_seq->data();
    delete new_seq;
    delete data;
    return status;
  }

  if (create_midedge) {
    status = add_mid_edge_nodes( new_seq );
    if (MB_SUCCESS != status)
      return status;
  }
  if (create_midface) {
    status = add_mid_face_nodes( new_seq );
    if (MB_SUCCESS != status)
      return status;
  }
  if (create_midvolm) {
    status = add_mid_volume_nodes( new_seq );
    if (MB_SUCCESS != status)
      return status;
  }
  
  return status;

}

Definition at line 647 of file HigherOrderFactory.cpp.

{
  unsigned num_corners = CN::VerticesPerEntity( src->type() );
  return copy_nodes( src, dst, num_corners, 0, 0 );
}

Definition at line 654 of file HigherOrderFactory.cpp.

{
  if (!src->has_mid_edge_nodes() || !dst->has_mid_edge_nodes())
    return MB_FAILURE;
  
  unsigned num_corners = CN::VerticesPerEntity( src->type() );
  unsigned num_edges = (src->type() == MBEDGE) ? 1 : CN::NumSubEntities( src->type(), 1 );
  return copy_nodes( src, dst, num_edges, num_corners, num_corners );
}

Definition at line 676 of file HigherOrderFactory.cpp.

{
  if (!src->has_mid_face_nodes() || !dst->has_mid_face_nodes())
    return MB_FAILURE;
  
  unsigned src_offset = CN::VerticesPerEntity( src->type() );
  unsigned dst_offset = src_offset;
  if (src->has_mid_edge_nodes())
    src_offset += CN::NumSubEntities( src->type(), 1 );
  if (dst->has_mid_edge_nodes())
    dst_offset += CN::NumSubEntities( dst->type(), 1 );
  unsigned num_faces = (CN::Dimension(src->type()) == 2) ? 1 : CN::NumSubEntities( src->type(), 2 );
  return copy_nodes( src, dst, num_faces, src_offset, dst_offset );
}

Definition at line 706 of file HigherOrderFactory.cpp.

{
  if (!src->has_mid_volume_nodes() || !dst->has_mid_volume_nodes())
    return MB_FAILURE;
  
  unsigned src_offset = CN::VerticesPerEntity( src->type() );
  unsigned dst_offset = src_offset;
  if (src->has_mid_edge_nodes())
    src_offset += CN::NumSubEntities( src->type(), 1 );
  if (dst->has_mid_edge_nodes())
    dst_offset += CN::NumSubEntities( dst->type(), 1 );
  if (src->has_mid_face_nodes())
    src_offset += CN::NumSubEntities( src->type(), 2 );
  if (dst->has_mid_face_nodes())
    dst_offset += CN::NumSubEntities( dst->type(), 2 );
  return copy_nodes( src, dst, 1, src_offset, dst_offset );
}
ErrorCode moab::HigherOrderFactory::copy_nodes ( ElementSequence src,
ElementSequence dst,
unsigned  nodes_per_elem_to_copy,
unsigned  src_conn_offset,
unsigned  dst_conn_offset 
) [private]

Definition at line 739 of file HigherOrderFactory.cpp.

{
  if (src->type() != dst->type())
    return MB_FAILURE;

  unsigned src_stride = src->nodes_per_element();
  unsigned dst_stride = dst->nodes_per_element();
  EntityHandle* src_conn = src->get_connectivity_array();
  EntityHandle* dst_conn = dst->get_connectivity_array();
  if (!src_conn || !dst_conn)
    return MB_FAILURE;
  
  if (dst->start_handle() < src->start_handle() ||
      dst->end_handle()   > src->end_handle())
    return MB_FAILURE;
  
  src_conn += (dst->start_handle() - src->start_handle()) * src_stride;
  EntityID count = dst->size();
  for (EntityID i = 0; i < count; ++i) {
    for (unsigned j = 0; j < nodes_per_elem; ++j)
      dst_conn[j+dst_offset] = src_conn[j+src_offset];
    src_conn += src_stride; 
    dst_conn += dst_stride;
  }
  
  return MB_SUCCESS;
}

Definition at line 48 of file HigherOrderFactory.cpp.

{
 // if(mMapInitialized)
  //  return;

  for(EntityType i=MBVERTEX; i<MBMAXTYPE; i++)
  {
    const CN::ConnMap& canon_map = CN::mConnectivityMap[i][0];
    unsigned char (&this_map)[8][8] = mNodeMap[i];
    int num_node = CN::VerticesPerEntity(i);
    for(int j=0; j<canon_map.num_sub_elements; j++)
    {
      unsigned char x = canon_map.conn[j][0];
      unsigned char y = canon_map.conn[j][1];
      this_map[x][y] = num_node;
      this_map[y][x] = num_node;
      num_node++;
    }
  }

  //mMapInitialized = true;
}
ErrorCode moab::HigherOrderFactory::remove_ho_nodes ( ElementSequence seq,
EntityHandle  start,
EntityHandle  end,
int  nodes_per_elem,
int  elem_conn_offset,
Tag  deletable_nodes 
) [private]

MOAB, a Mesh-Oriented datABase, is a software component for creating, storing and accessing finite element mesh data.

Copyright 2004 Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Coroporation, the U.S. Government retains certain rights in this software.

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

Definition at line 863 of file HigherOrderFactory.cpp.

{
  if (start < seq->start_handle() || end > seq->end_handle())
    return MB_ENTITY_NOT_FOUND;
  EntityHandle* array = seq->get_connectivity_array();
  if (!array)
    return MB_NOT_IMPLEMENTED;
   
  std::set<EntityHandle> nodes_processed;
  for (EntityHandle i = start; i <= end; ++i) {  // for each element
    for (int j = 0; j < nodes_per_elem; ++j) {  // for each HO node to remove
      const EntityID elem = (i - seq->start_handle()); // element index
      const int conn_idx = j + elem_conn_offset;
      const EntityID index = elem * seq->nodes_per_element() + conn_idx;
      if (array[index] && nodes_processed.insert( array[index] ).second) {
        if (tag_for_deletion( i, conn_idx, seq )) {
          unsigned char bit = 0x1;
          mMB->tag_set_data( deletable_nodes, &(array[index]), 1, &bit );
        }
      }
    }
  }
  
  return MB_SUCCESS;
}
ErrorCode moab::HigherOrderFactory::remove_mid_edge_nodes ( ElementSequence seq,
EntityHandle  start,
EntityHandle  stop,
Tag  deletable_ndoes 
) [private]

Definition at line 791 of file HigherOrderFactory.cpp.

{
  int count;
  int offset;
  if (seq->type() == MBEDGE) {
    count = 1;
    offset = 2;
  }
  else {
    count = CN::NumSubEntities( seq->type(), 1 );
    offset = CN::VerticesPerEntity( seq->type() );
  }
  
  return remove_ho_nodes( seq, start, end, count, offset, deletable_nodes );
}
ErrorCode moab::HigherOrderFactory::remove_mid_face_nodes ( ElementSequence seq,
EntityHandle  start,
EntityHandle  stop,
Tag  deletable_ndoes 
) [private]

Definition at line 812 of file HigherOrderFactory.cpp.

{
  int count;
  if (CN::Dimension(seq->type()) == 2)
    count = 1;
  else 
    count = CN::NumSubEntities( seq->type(), 2 );
  int offset = CN::VerticesPerEntity( seq->type() );
  if (seq->has_mid_edge_nodes())
    offset += CN::NumSubEntities( seq->type(), 1 );
  
  return remove_ho_nodes( seq, start, end, count, offset, deletable_nodes );
}
ErrorCode moab::HigherOrderFactory::remove_mid_volume_nodes ( ElementSequence seq,
EntityHandle  start,
EntityHandle  stop,
Tag  deletable_ndoes 
) [private]

Definition at line 830 of file HigherOrderFactory.cpp.

{
  int offset = CN::VerticesPerEntity( seq->type() );
  if (seq->has_mid_edge_nodes())
    offset += CN::NumSubEntities( seq->type(), 1 );
  if (seq->has_mid_face_nodes())
    offset += CN::NumSubEntities( seq->type(), 2 );
  
  return remove_ho_nodes( seq, start, end, 1, offset, deletable_nodes );
}
bool moab::HigherOrderFactory::tag_for_deletion ( EntityHandle  element_with_node,
int  node_index_in_elem_connectivity,
ElementSequence sequence 
) [private]

Definition at line 895 of file HigherOrderFactory.cpp.

{
  //get type of this sequence
  EntityType this_type = seq->type();

  //get dimension of 'parent' element
  int this_dimension = mMB->dimension_from_handle( parent_handle );

  //tells us if higher order node is on 
  int dimension, side_number; 
  CN::HONodeParent( this_type, seq->nodes_per_element(),
                      conn_index, dimension, side_number );  

  //it MUST be a higher-order node
  bool delete_node = false;

  assert( dimension != -1 );
  assert( side_number != -1 );

  //could be a mid-volume/face/edge node on a hex/face/edge respectively
  //if so...delete it bc/ no one else owns it too
  std::vector<EntityHandle> connectivity;
  if( dimension == this_dimension && side_number == 0 )
    delete_node = true;
  else //the node could also be on a lower order entity of 'tmp_entity' 
  {
    //get 'side' of 'parent_handle' that node is on 
    EntityHandle target_entity = 0;
    mMB->side_element( parent_handle, dimension, side_number, target_entity );

    if( target_entity )
    {
      AEntityFactory *a_fact = mMB->a_entity_factory();
      EntityHandle low_meshset;
      int dum;
      low_meshset = CREATE_HANDLE(MBENTITYSET, 0, dum);

      //just get corner nodes of target_entity
      connectivity.clear();
      mMB->get_connectivity(&( target_entity), 1, connectivity, true  );

      //for each node, get all common adjacencies of nodes in 'parent_handle' 
      std::vector<EntityHandle> adj_list_1, adj_list_2, adj_entities;
      a_fact->get_adjacencies(connectivity[0], adj_list_1);

      // remove meshsets
      adj_list_1.erase(std::remove_if(adj_list_1.begin(), adj_list_1.end(), 
           std::bind2nd(std::greater<EntityHandle>(),low_meshset)), adj_list_1.end());

      size_t i; 
      for( i=1; i<connectivity.size(); i++)
      {
        adj_list_2.clear();
        a_fact->get_adjacencies(connectivity[i], adj_list_2);

        // remove meshsets
        adj_list_2.erase(std::remove_if(adj_list_2.begin(), adj_list_2.end(), 
             std::bind2nd(std::greater<EntityHandle>(),low_meshset)), adj_list_2.end());
       
        //intersect the 2 lists 
        adj_entities.clear();
        std::set_intersection(adj_list_1.begin(), adj_list_1.end(), 
                              adj_list_2.begin(), adj_list_2.end(), 
                              std::back_inserter< std::vector<EntityHandle> >(adj_entities));
        adj_list_1.clear();
        adj_list_1 = adj_entities;
      } 

      assert( adj_entities.size() );  //has to have at least one adjacency 

      //see if node is in other elements, not in this sequence...if so, delete it 
      for( i=0; i<adj_entities.size(); i++)
      {
        if( adj_entities[i] >= seq->start_handle() &&
            adj_entities[i] <= seq->end_handle() )
        {
          delete_node = false;
          break;
        }
        else 
          delete_node = true;
      }             
    }
    else //there is no lower order entity that also contains node 
      delete_node = true;
  }

  return delete_node;
}

Definition at line 665 of file HigherOrderFactory.cpp.

{
  if (!dst->has_mid_edge_nodes())
    return MB_FAILURE;
  
  unsigned num_corners = CN::VerticesPerEntity( dst->type() );
  unsigned num_edges = (dst->type() == MBEDGE) ? 1 : CN::NumSubEntities( dst->type(), 1 );
  return zero_nodes( dst, num_edges, num_corners );
}

Definition at line 692 of file HigherOrderFactory.cpp.

{
  if (!dst->has_mid_face_nodes())
    return MB_FAILURE;
  
  unsigned dst_offset = CN::VerticesPerEntity( dst->type() );
  if (dst->has_mid_edge_nodes())
    dst_offset += CN::NumSubEntities( dst->type(), 1 );
  unsigned num_faces = (CN::Dimension(dst->type()) == 2) ? 1 : CN::NumSubEntities( dst->type(), 2 );
  return zero_nodes( dst, num_faces, dst_offset );
}

Definition at line 725 of file HigherOrderFactory.cpp.

{
  if (!dst->has_mid_volume_nodes())
    return MB_FAILURE;
  
  unsigned dst_offset = CN::VerticesPerEntity( dst->type() );
  if (dst->has_mid_edge_nodes())
    dst_offset += CN::NumSubEntities( dst->type(), 1 );
  if (dst->has_mid_face_nodes())
    dst_offset += CN::NumSubEntities( dst->type(), 2 );
  return zero_nodes( dst, 1, dst_offset );
}
ErrorCode moab::HigherOrderFactory::zero_nodes ( ElementSequence dst,
unsigned  nodes_per_elem_to_zero,
unsigned  dst_conn_offset 
) [private]

Definition at line 772 of file HigherOrderFactory.cpp.

{
  unsigned dst_stride = dst->nodes_per_element();
  EntityHandle* dst_conn = dst->get_connectivity_array();
  if (!dst_conn)
    return MB_FAILURE;
  
  EntityID count = dst->size();
  for (EntityID i = 0; i < count; ++i) {
    std::fill( dst_conn + offset, dst_conn + offset + nodes_per_elem, 0 );
    dst_conn += dst_stride;
  }
  
  return MB_SUCCESS;
}

Member Data Documentation

Definition at line 58 of file HigherOrderFactory.hpp.

Definition at line 51 of file HigherOrderFactory.hpp.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines