moab
HigherOrderFactory.cpp
Go to the documentation of this file.
00001 
00017 #ifdef WIN32
00018 #ifdef _DEBUG
00019 // turn off warnings that say they debugging identifier has been truncated
00020 // this warning comes up when using some STL containers
00021 #pragma warning(disable : 4786)
00022 #endif
00023 #endif
00024 
00025 #include "moab/HigherOrderFactory.hpp"
00026 #include "SequenceManager.hpp"
00027 #include "UnstructuredElemSeq.hpp"
00028 #include "VertexSequence.hpp"
00029 #include "AEntityFactory.hpp"
00030 #include "moab/Core.hpp"
00031 #include "moab/CN.hpp"
00032 #include <assert.h>
00033 #include <algorithm>
00034 
00035 namespace moab {
00036 
00037 using namespace std;
00038 
00039 HigherOrderFactory::HigherOrderFactory(Core* MB, Interface::HONodeAddedRemoved* function_object) 
00040   : mMB(MB), mHONodeAddedRemoved(function_object)
00041 {
00042   initialize_map();
00043 }
00044 HigherOrderFactory::~HigherOrderFactory() {}
00045 
00046 //bool HigherOrderFactory::mMapInitialized = false;
00047 
00048 void HigherOrderFactory::initialize_map()
00049 {
00050  // if(mMapInitialized)
00051   //  return;
00052 
00053   for(EntityType i=MBVERTEX; i<MBMAXTYPE; i++)
00054   {
00055     const CN::ConnMap& canon_map = CN::mConnectivityMap[i][0];
00056     unsigned char (&this_map)[8][8] = mNodeMap[i];
00057     int num_node = CN::VerticesPerEntity(i);
00058     for(int j=0; j<canon_map.num_sub_elements; j++)
00059     {
00060       unsigned char x = canon_map.conn[j][0];
00061       unsigned char y = canon_map.conn[j][1];
00062       this_map[x][y] = num_node;
00063       this_map[y][x] = num_node;
00064       num_node++;
00065     }
00066   }
00067 
00068   //mMapInitialized = true;
00069 }
00070 
00071 
00072 ErrorCode HigherOrderFactory::convert( const EntityHandle meshset, 
00073                                          const bool mid_edge_nodes, 
00074                                          const bool mid_face_nodes, 
00075                                          const bool mid_volume_nodes )
00076 {
00077   Range entities;
00078   mMB->get_entities_by_handle(meshset, entities, true);
00079   return convert( entities, mid_edge_nodes, mid_face_nodes, mid_volume_nodes );
00080 }
00081 
00082 ErrorCode HigherOrderFactory::convert( const Range& entities,
00083                                          const bool mid_edge_nodes, 
00084                                          const bool mid_face_nodes, 
00085                                          const bool mid_volume_nodes )
00086 
00087 {
00088 
00089   // TODO --  add some more code to prevent from splitting of entity sequences when we don't need to.
00090   // Say we have all hex8's in our mesh and 3 falses are passed in.  In the end, no conversion will
00091   // happen, but the sequences could still be split up.
00092 
00093   // find out what entity sequences we need to convert 
00094   // and where, if necessary, to split them
00095 
00096   SequenceManager* seq_manager = mMB->sequence_manager();
00097   Range::const_pair_iterator p_iter;
00098   for (p_iter = entities.const_pair_begin(); p_iter != entities.const_pair_end(); ++p_iter) {
00099     
00100     EntityHandle h = p_iter->first;
00101     while (h <= p_iter->second) {
00102       
00103       EntitySequence* seq;
00104       ErrorCode rval = seq_manager->find( h, seq );
00105       if (MB_SUCCESS != rval)
00106         return rval;
00107       
00108       if (seq->type() == MBVERTEX || seq->type() >= MBENTITYSET)
00109         return MB_TYPE_OUT_OF_RANGE;
00110       
00111         // make sequence is not structured mesh
00112       ElementSequence* elemseq = static_cast<ElementSequence*>(seq);
00113       if (NULL == elemseq->get_connectivity_array())
00114         return MB_NOT_IMPLEMENTED;
00115       
00116       EntityHandle last = p_iter->second;
00117       if (last > seq->end_handle())
00118         last = seq->end_handle();
00119       
00120       rval = convert_sequence( elemseq, h, last, 
00121                                mid_edge_nodes,
00122                                mid_face_nodes,
00123                                mid_volume_nodes );
00124       if (MB_SUCCESS != rval)
00125         return rval;
00126         
00127       h = last + 1;
00128     }
00129   }
00130   
00131   return MB_SUCCESS;
00132 } 
00133 
00134 
00135 ErrorCode HigherOrderFactory::convert_sequence( ElementSequence* seq, 
00136                                                   EntityHandle start,
00137                                                   EntityHandle end,
00138                                                   bool mid_edge_nodes, 
00139                                                   bool mid_face_nodes, 
00140                                                   bool mid_volume_nodes)
00141 {
00142 
00143   ErrorCode status = MB_SUCCESS;
00144 
00145   // lets make sure parameters are ok before we continue
00146   switch (seq->type()) {
00147     default: return MB_TYPE_OUT_OF_RANGE; 
00148     case MBEDGE:
00149       mid_face_nodes = false;
00150     case MBTRI:
00151     case MBQUAD:
00152       mid_volume_nodes = false;
00153     case MBTET:
00154     case MBHEX:
00155     case MBPRISM:
00156     case MBPYRAMID:
00157     case MBKNIFE:
00158       break;
00159   }
00160 
00161     // calculate number of nodes in target configuration
00162   unsigned nodes_per_elem = CN::VerticesPerEntity( seq->type() );
00163   if (mid_edge_nodes)
00164     nodes_per_elem += (seq->type() == MBEDGE) ? 1 : CN::NumSubEntities( seq->type(), 1 );
00165   if (mid_face_nodes)
00166     nodes_per_elem += (CN::Dimension(seq->type()) == 2) ? 1 : CN::NumSubEntities( seq->type(), 2 );
00167   if (mid_volume_nodes) 
00168     nodes_per_elem += 1;
00169   
00170   if (nodes_per_elem == seq->nodes_per_element())
00171     return MB_SUCCESS;
00172   
00173   Tag deletable_nodes;
00174   status = mMB->tag_get_handle(0, 1, MB_TYPE_BIT, deletable_nodes, MB_TAG_CREAT|MB_TAG_BIT);
00175   if (MB_SUCCESS != status)
00176     return status;
00177   
00178   UnstructuredElemSeq* new_seq = new UnstructuredElemSeq( start,
00179                                                           end - start + 1,
00180                                                           nodes_per_elem,
00181                                                           end - start + 1 );
00182   
00183   copy_corner_nodes( seq, new_seq );
00184 
00185   if (seq->has_mid_edge_nodes() && mid_edge_nodes) 
00186     status = copy_mid_edge_nodes( seq, new_seq );
00187   else if (seq->has_mid_edge_nodes() && !mid_edge_nodes)
00188     status = remove_mid_edge_nodes( seq, start, end, deletable_nodes );
00189   else if (!seq->has_mid_edge_nodes() && mid_edge_nodes)
00190     status = zero_mid_edge_nodes( new_seq );
00191   if (MB_SUCCESS != status)
00192     return status;
00193 
00194   if (seq->has_mid_face_nodes() && mid_face_nodes) 
00195     status = copy_mid_face_nodes( seq, new_seq );
00196   else if (seq->has_mid_face_nodes() && !mid_face_nodes)
00197     status = remove_mid_face_nodes( seq, start, end, deletable_nodes );
00198   else if (!seq->has_mid_face_nodes() && mid_face_nodes)
00199     status = zero_mid_face_nodes( new_seq );
00200   if (MB_SUCCESS != status) {
00201     mMB->tag_delete( deletable_nodes );
00202     return status;
00203   }
00204  
00205   if (seq->has_mid_volume_nodes() && mid_volume_nodes) 
00206     status = copy_mid_volume_nodes( seq, new_seq );
00207   else if (seq->has_mid_volume_nodes() && !mid_volume_nodes)
00208     status = remove_mid_volume_nodes( seq, start, end, deletable_nodes );
00209   else if (!seq->has_mid_volume_nodes() && mid_volume_nodes)
00210     status = zero_mid_volume_nodes( new_seq );
00211   if (MB_SUCCESS != status) {
00212     mMB->tag_delete( deletable_nodes );
00213     return status;
00214   }
00215 
00216   // gather nodes that were marked
00217   Range nodes;
00218   mMB->get_entities_by_type_and_tag(0, MBVERTEX, &deletable_nodes, NULL, 1, nodes);
00219 
00220   //EntityHandle low_meshset;
00221   //int dum;
00222   //low_meshset = CREATE_HANDLE(MBENTITYSET, 0, dum);
00223   
00224   for(Range::iterator iter = nodes.begin(); iter != nodes.end(); ++iter)
00225   {
00226     unsigned char marked = 0;
00227     mMB->tag_get_data(deletable_nodes, &(*iter), 1, &marked);
00228     if(marked)
00229     {
00230       // we can delete it
00231       if(mHONodeAddedRemoved)
00232         mHONodeAddedRemoved->node_removed( *iter );
00233       mMB->delete_entities(&(*iter), 1);
00234     }
00235   }
00236   
00237   const bool create_midedge = !seq->has_mid_edge_nodes() && mid_edge_nodes;
00238   const bool create_midface = !seq->has_mid_face_nodes() && mid_face_nodes;
00239   const bool create_midvolm = !seq->has_mid_volume_nodes() && mid_volume_nodes;
00240   
00241   mMB->tag_delete(deletable_nodes);
00242 
00243   status = mMB->sequence_manager()->replace_subsequence( new_seq );
00244   if (MB_SUCCESS != status) {
00245     SequenceData* data = new_seq->data();
00246     delete new_seq;
00247     delete data;
00248     return status;
00249   }
00250 
00251   if (create_midedge) {
00252     status = add_mid_edge_nodes( new_seq );
00253     if (MB_SUCCESS != status)
00254       return status;
00255   }
00256   if (create_midface) {
00257     status = add_mid_face_nodes( new_seq );
00258     if (MB_SUCCESS != status)
00259       return status;
00260   }
00261   if (create_midvolm) {
00262     status = add_mid_volume_nodes( new_seq );
00263     if (MB_SUCCESS != status)
00264       return status;
00265   }
00266   
00267   return status;
00268 
00269 }
00270 
00271 
00272 ErrorCode HigherOrderFactory::add_mid_volume_nodes(ElementSequence* seq)
00273 {
00274   EntityType this_type = seq->type();
00275   SequenceManager* seq_manager = mMB->sequence_manager();
00276 
00277   // find out where in the connectivity list to add these new mid volume nodes
00278   int edge_factor = seq->has_mid_edge_nodes() ? 1 : 0;
00279   int face_factor = seq->has_mid_face_nodes() ? 1 : 0;
00280   // offset by number of higher order nodes on edges if they exist
00281   int num_corner_nodes = CN::VerticesPerEntity(this_type);
00282   int new_node_index = num_corner_nodes;
00283   new_node_index += edge_factor * CN::mConnectivityMap[this_type][0].num_sub_elements;
00284   new_node_index += face_factor * CN::mConnectivityMap[this_type][1].num_sub_elements;
00285 
00286   EntityHandle* element = seq->get_connectivity_array();
00287   EntityHandle curr_handle = seq->start_handle();
00288   int nodes_per_element = seq->nodes_per_element();
00289   EntityHandle* end_element = element + nodes_per_element * (seq->size());
00290 
00291   // iterate over the elements
00292   for(; element < end_element; element+=nodes_per_element)
00293   {
00294     // find the centroid of this element
00295     double tmp_coords[3], sum_coords[3] = {0,0,0};
00296     EntitySequence* eseq=NULL;
00297     for(int i=0; i<num_corner_nodes; i++)
00298     {
00299       seq_manager->find(element[i], eseq);
00300       static_cast<VertexSequence*>(eseq)->get_coordinates(
00301           element[i], tmp_coords[0], tmp_coords[1], tmp_coords[2]
00302           );
00303       sum_coords[0] += tmp_coords[0];
00304       sum_coords[1] += tmp_coords[1];
00305       sum_coords[2] += tmp_coords[2];
00306     }
00307     sum_coords[0] /= num_corner_nodes;
00308     sum_coords[1] /= num_corner_nodes;
00309     sum_coords[2] /= num_corner_nodes;
00310 
00311     // create a new vertex at the centroid
00312     mMB->create_vertex(sum_coords, element[new_node_index]);
00313     
00314     if(mHONodeAddedRemoved)
00315       mHONodeAddedRemoved->node_added(element[new_node_index], curr_handle);
00316 
00317     curr_handle++;
00318   }
00319 
00320   return MB_SUCCESS;
00321 }
00322 
00323 
00324 ErrorCode HigherOrderFactory::add_mid_face_nodes(ElementSequence* seq)
00325 {
00326   EntityType this_type = seq->type();
00327   SequenceManager* seq_manager = mMB->sequence_manager();
00328   int num_vertices = CN::VerticesPerEntity(this_type);
00329   int num_edges = CN::mConnectivityMap[this_type][0].num_sub_elements;
00330   num_edges = seq->has_mid_edge_nodes() ? num_edges : 0;
00331   int num_faces = CN::mConnectivityMap[this_type][1].num_sub_elements;
00332 
00333   const CN::ConnMap& entity_faces = CN::mConnectivityMap[this_type][1];
00334 
00335   EntityHandle* element = seq->get_connectivity_array();
00336   EntityHandle curr_handle = seq->start_handle();
00337   int nodes_per_element = seq->nodes_per_element();
00338   EntityHandle* end_element = element + nodes_per_element * (seq->size());
00339 
00340   EntityHandle tmp_face_conn[4];  // max face nodes = 4
00341   std::vector<EntityHandle> adjacent_entities(4);
00342 
00343   double tmp_coords[3];
00344   
00345   // iterate over the elements
00346   for(; element < end_element; element+=nodes_per_element)
00347   {
00348     // for each edge in this entity
00349     for(int i=0; i<num_faces; i++)
00350     {
00351       // a node was already assigned
00352       if(element[i+num_edges+num_vertices] != 0)
00353         continue;
00354 
00355       tmp_face_conn[0] = element[entity_faces.conn[i][0]];
00356       tmp_face_conn[1] = element[entity_faces.conn[i][1]];
00357       tmp_face_conn[2] = element[entity_faces.conn[i][2]];
00358       if(entity_faces.num_corners_per_sub_element[i] == 4)
00359         tmp_face_conn[3] = element[entity_faces.conn[i][3]];
00360       else
00361         tmp_face_conn[3] = 0;
00362 
00363       EntityHandle already_made_node = center_node_exist(tmp_face_conn, adjacent_entities);
00364       
00365       if(already_made_node)
00366       {
00367         element[i+num_edges+num_vertices] = already_made_node;
00368       }
00369       // create a node
00370       else
00371       {
00372         EntitySequence* tmp_sequence = NULL;
00373         double sum_coords[3] = {0,0,0};
00374         int max_nodes = entity_faces.num_corners_per_sub_element[i];
00375         for(int k=0; k<max_nodes; k++)
00376         {
00377           seq_manager->find(tmp_face_conn[k], tmp_sequence);
00378           static_cast<VertexSequence*>(tmp_sequence)->get_coordinates( 
00379               tmp_face_conn[k], tmp_coords[0], tmp_coords[1], tmp_coords[2]);
00380           sum_coords[0] += tmp_coords[0];
00381           sum_coords[1] += tmp_coords[1];
00382           sum_coords[2] += tmp_coords[2];
00383         }
00384 
00385         sum_coords[0] /= max_nodes;
00386         sum_coords[1] /= max_nodes;
00387         sum_coords[2] /= max_nodes;
00388 
00389         mMB->create_vertex(sum_coords, element[i+num_edges+num_vertices]);
00390       }
00391 
00392       if(mHONodeAddedRemoved)
00393         mHONodeAddedRemoved->node_added(element[i+num_edges+num_vertices], curr_handle);
00394       
00395     }
00396 
00397     curr_handle++;
00398 
00399   }
00400 
00401   return MB_SUCCESS;
00402 }
00403 
00404 
00405 ErrorCode HigherOrderFactory::add_mid_edge_nodes(ElementSequence* seq)
00406 {
00407   // for each node, need to see if it was already created.
00408   EntityType this_type = seq->type();
00409   SequenceManager* seq_manager = mMB->sequence_manager();
00410 
00411   // offset by number of corner nodes
00412   int num_vertices = CN::VerticesPerEntity(this_type);
00413   int num_edges = CN::mConnectivityMap[this_type][0].num_sub_elements;
00414 
00415   const CN::ConnMap& entity_edges = CN::mConnectivityMap[this_type][0];
00416   
00417   EntityHandle* element = seq->get_connectivity_array();
00418   EntityHandle curr_handle = seq->start_handle();
00419   int nodes_per_element = seq->nodes_per_element();
00420   EntityHandle* end_element = element + nodes_per_element * (seq->size());
00421 
00422   EntityHandle tmp_edge_conn[2];
00423   std::vector<EntityHandle> adjacent_entities(32);
00424 
00425   double tmp_coords[3];
00426 
00427   // iterate over the elements
00428   for(; element < end_element; element+=nodes_per_element)
00429   {
00430     // for each edge in this entity
00431     for(int i=0; i<num_edges; i++)
00432     {
00433       // a node was already assigned
00434       if(element[i+num_vertices] != 0)
00435         continue;
00436 
00437       tmp_edge_conn[0] = element[entity_edges.conn[i][0]];
00438       tmp_edge_conn[1] = element[entity_edges.conn[i][1]];
00439 
00440       EntityHandle already_made_node = center_node_exist(tmp_edge_conn[0], tmp_edge_conn[1],
00441           adjacent_entities);
00442       
00443       if(already_made_node)
00444       {
00445         element[i+num_vertices] = already_made_node;
00446       }
00447       // create a node
00448       else
00449       {
00450         EntitySequence* tmp_sequence = NULL;
00451         double sum_coords[3] = {0,0,0};
00452         seq_manager->find(tmp_edge_conn[0], tmp_sequence);
00453         static_cast<VertexSequence*>(tmp_sequence)->get_coordinates( 
00454             tmp_edge_conn[0], tmp_coords[0], tmp_coords[1], tmp_coords[2]);
00455         sum_coords[0] += tmp_coords[0];
00456         sum_coords[1] += tmp_coords[1];
00457         sum_coords[2] += tmp_coords[2];
00458         seq_manager->find(tmp_edge_conn[1], tmp_sequence);
00459         static_cast<VertexSequence*>(tmp_sequence)->get_coordinates( 
00460             tmp_edge_conn[1], tmp_coords[0], tmp_coords[1], tmp_coords[2]);
00461         sum_coords[0] = (sum_coords[0] + tmp_coords[0]) /2;
00462         sum_coords[1] = (sum_coords[1] + tmp_coords[1]) /2;
00463         sum_coords[2] = (sum_coords[2] + tmp_coords[2]) /2;
00464 
00465         mMB->create_vertex(sum_coords, element[i+num_vertices]);
00466       }
00467 
00468       if(mHONodeAddedRemoved)
00469         mHONodeAddedRemoved->node_added(element[i+num_vertices], curr_handle);
00470       
00471     }
00472 
00473     curr_handle++;
00474 
00475   }
00476 
00477   return MB_SUCCESS;
00478 }
00479 
00480 EntityHandle HigherOrderFactory::center_node_exist( EntityHandle corner1, 
00481     EntityHandle corner2, std::vector<EntityHandle>& adj_entities)
00482 {
00483   AEntityFactory* a_fact = mMB->a_entity_factory();
00484   std::vector<EntityHandle> adj_corner1(32);
00485   std::vector<EntityHandle> adj_corner2(32);
00486 
00487   // create needed vertex adjacencies
00488   if (!a_fact->vert_elem_adjacencies())
00489     a_fact->create_vert_elem_adjacencies();
00490 
00491   // vectors are returned sorted
00492   
00493   a_fact->get_adjacencies(corner1, adj_corner1);
00494   a_fact->get_adjacencies(corner2, adj_corner2);
00495 
00496   // these are the entities adjacent to both nodes
00497   adj_entities.clear();
00498   std::set_intersection(adj_corner1.begin(), adj_corner1.end(), adj_corner2.begin(),
00499       adj_corner2.end(), std::back_inserter<std::vector<EntityHandle> >(adj_entities));
00500 
00501 
00502   // iterate of the entities to find a mid node
00503   const EntityHandle* conn;
00504   int conn_size = 0;
00505   for(std::vector<EntityHandle>::iterator iter = adj_entities.begin();
00506       iter != adj_entities.end(); )
00507   {
00508     EntityType this_type = TYPE_FROM_HANDLE(*iter);
00509     if (this_type == MBENTITYSET) {
00510       ++iter;
00511       continue;
00512     }
00513     mMB->get_connectivity(*iter, conn, conn_size);
00514     // if this entity has mid edge nodes
00515     if(CN::HasMidEdgeNodes(this_type, conn_size))
00516     {
00517       // find out at which index the mid node should be at
00518       int first_node = std::find(conn, conn+conn_size, corner1) - conn;
00519       int second_node = std::find(conn, conn+conn_size, corner2) - conn;
00520       if(first_node == conn_size || second_node == conn_size)
00521         assert("We should always find our nodes no matter what" == NULL);
00522       int high_node_index = mNodeMap[this_type][first_node][second_node];
00523       if(conn[high_node_index] != 0)
00524         return conn[high_node_index];
00525       ++iter;
00526     }
00527     else
00528     {
00529       iter = adj_entities.erase(iter);
00530     }
00531   }
00532 
00533   return 0;
00534 
00535 }
00536 
00537 EntityHandle HigherOrderFactory::center_node_exist( EntityHandle corners[4], 
00538     std::vector<EntityHandle>& adj_entities)
00539 {
00540   AEntityFactory* a_fact = mMB->a_entity_factory();
00541   std::vector<EntityHandle> adj_corner[4];
00542   int num_nodes = corners[3] == 0 ? 3 : 4;
00543   int i = 0;
00544 
00545   // create needed vertex adjacencies
00546   if (!a_fact->vert_elem_adjacencies())
00547     a_fact->create_vert_elem_adjacencies();
00548 
00549   // vectors are returned sorted
00550   for(i=0; i<num_nodes; i++)
00551     a_fact->get_adjacencies(corners[i], adj_corner[i]);
00552 
00553   // these are the entities adjacent to both nodes
00554   for(i=1; i<num_nodes; i++)
00555   {
00556     adj_entities.clear();
00557     std::set_intersection(adj_corner[i-1].begin(), adj_corner[i-1].end(), adj_corner[i].begin(),
00558       adj_corner[i].end(), std::back_inserter<std::vector<EntityHandle> >(adj_entities));
00559     adj_corner[i].swap(adj_entities);
00560   }
00561   adj_entities.swap(adj_corner[i-1]);
00562   
00563 
00564   // iterate of the entities to find a mid node
00565   const EntityHandle* conn;
00566   int conn_size = 0;
00567   for(std::vector<EntityHandle>::iterator iter = adj_entities.begin();
00568       iter != adj_entities.end(); )
00569   {
00570     EntityType this_type = TYPE_FROM_HANDLE(*iter);
00571     if (this_type == MBENTITYSET) {
00572       ++iter;
00573       continue;
00574     }
00575     const CN::ConnMap& entity_faces = CN::mConnectivityMap[this_type][1];
00576     mMB->get_connectivity(*iter, conn, conn_size);
00577     int offset = CN::VerticesPerEntity(this_type);
00578     if(CN::HasMidEdgeNodes(this_type, conn_size))
00579       offset += CN::mConnectivityMap[this_type][0].num_sub_elements;
00580 
00581     // if this entity has mid face nodes
00582     if(CN::HasMidFaceNodes(this_type, conn_size))
00583     {
00584       int k;
00585       int indexes[4];
00586       for(k=0; k<num_nodes; k++)
00587         indexes[k] = std::find(conn, conn+conn_size, corners[k]) - conn;
00588       
00589       // find out at which index the mid node should be at
00590       for(k=0; k<entity_faces.num_sub_elements; k++)
00591       {
00592         if(CN::VerticesPerEntity(entity_faces.target_type[k]) != num_nodes)
00593           continue;
00594 
00595         int* pivot = std::find(indexes, indexes+num_nodes, entity_faces.conn[k][0]);
00596         if(pivot == indexes+num_nodes)
00597           continue;
00598 
00599         if(pivot != indexes)
00600           std::rotate(indexes, pivot, indexes+num_nodes);
00601 
00602         if(std::equal(indexes, indexes+num_nodes, entity_faces.conn[k]))
00603         {
00604           if(conn[k+offset] != 0)
00605             return conn[k+offset];
00606           k=entity_faces.num_sub_elements;
00607         }
00608         else
00609         {
00610           int temp = indexes[1];
00611           indexes[1] = indexes[num_nodes-1];
00612           indexes[num_nodes-1] = temp;
00613           if(std::equal(indexes, indexes+num_nodes, entity_faces.conn[k]))
00614           {
00615             if(conn[k+offset] != 0)
00616               return conn[k+offset];
00617             k=entity_faces.num_sub_elements;
00618           }
00619         }
00620       }
00621       ++iter;
00622     }
00623     else
00624     {
00625       iter = adj_entities.erase(iter);
00626     }
00627   }
00628 
00629   return 0;
00630 
00631 }
00632 
00633 bool HigherOrderFactory::add_center_node(EntityType this_type, EntityHandle* element_conn, 
00634     int conn_size, EntityHandle corner_node1, EntityHandle corner_node2, 
00635     EntityHandle center_node)
00636 {
00637   int first_node = std::find(element_conn, element_conn+conn_size, corner_node1) - element_conn;
00638   int second_node = std::find(element_conn, element_conn+conn_size, corner_node2) - element_conn;
00639   if(first_node == conn_size || second_node == conn_size)
00640     assert("We should always find our nodes no matter what" == NULL);
00641   int high_node_index = mNodeMap[this_type][first_node][second_node];
00642   element_conn[high_node_index] = center_node;  
00643   return true;
00644 }
00645 
00646 ErrorCode 
00647 HigherOrderFactory::copy_corner_nodes( ElementSequence* src, ElementSequence* dst )
00648 {
00649   unsigned num_corners = CN::VerticesPerEntity( src->type() );
00650   return copy_nodes( src, dst, num_corners, 0, 0 );
00651 }
00652 
00653 ErrorCode 
00654 HigherOrderFactory::copy_mid_edge_nodes( ElementSequence* src, ElementSequence* dst )
00655 {
00656   if (!src->has_mid_edge_nodes() || !dst->has_mid_edge_nodes())
00657     return MB_FAILURE;
00658   
00659   unsigned num_corners = CN::VerticesPerEntity( src->type() );
00660   unsigned num_edges = (src->type() == MBEDGE) ? 1 : CN::NumSubEntities( src->type(), 1 );
00661   return copy_nodes( src, dst, num_edges, num_corners, num_corners );
00662 }
00663 
00664 ErrorCode 
00665 HigherOrderFactory::zero_mid_edge_nodes( ElementSequence* dst )
00666 {
00667   if (!dst->has_mid_edge_nodes())
00668     return MB_FAILURE;
00669   
00670   unsigned num_corners = CN::VerticesPerEntity( dst->type() );
00671   unsigned num_edges = (dst->type() == MBEDGE) ? 1 : CN::NumSubEntities( dst->type(), 1 );
00672   return zero_nodes( dst, num_edges, num_corners );
00673 }
00674 
00675 ErrorCode 
00676 HigherOrderFactory::copy_mid_face_nodes( ElementSequence* src, ElementSequence* dst )
00677 {
00678   if (!src->has_mid_face_nodes() || !dst->has_mid_face_nodes())
00679     return MB_FAILURE;
00680   
00681   unsigned src_offset = CN::VerticesPerEntity( src->type() );
00682   unsigned dst_offset = src_offset;
00683   if (src->has_mid_edge_nodes())
00684     src_offset += CN::NumSubEntities( src->type(), 1 );
00685   if (dst->has_mid_edge_nodes())
00686     dst_offset += CN::NumSubEntities( dst->type(), 1 );
00687   unsigned num_faces = (CN::Dimension(src->type()) == 2) ? 1 : CN::NumSubEntities( src->type(), 2 );
00688   return copy_nodes( src, dst, num_faces, src_offset, dst_offset );
00689 }
00690 
00691 ErrorCode 
00692 HigherOrderFactory::zero_mid_face_nodes( ElementSequence* dst )
00693 {
00694   if (!dst->has_mid_face_nodes())
00695     return MB_FAILURE;
00696   
00697   unsigned dst_offset = CN::VerticesPerEntity( dst->type() );
00698   if (dst->has_mid_edge_nodes())
00699     dst_offset += CN::NumSubEntities( dst->type(), 1 );
00700   unsigned num_faces = (CN::Dimension(dst->type()) == 2) ? 1 : CN::NumSubEntities( dst->type(), 2 );
00701   return zero_nodes( dst, num_faces, dst_offset );
00702 }
00703 
00704 
00705 ErrorCode 
00706 HigherOrderFactory::copy_mid_volume_nodes( ElementSequence* src, ElementSequence* dst )
00707 {
00708   if (!src->has_mid_volume_nodes() || !dst->has_mid_volume_nodes())
00709     return MB_FAILURE;
00710   
00711   unsigned src_offset = CN::VerticesPerEntity( src->type() );
00712   unsigned dst_offset = src_offset;
00713   if (src->has_mid_edge_nodes())
00714     src_offset += CN::NumSubEntities( src->type(), 1 );
00715   if (dst->has_mid_edge_nodes())
00716     dst_offset += CN::NumSubEntities( dst->type(), 1 );
00717   if (src->has_mid_face_nodes())
00718     src_offset += CN::NumSubEntities( src->type(), 2 );
00719   if (dst->has_mid_face_nodes())
00720     dst_offset += CN::NumSubEntities( dst->type(), 2 );
00721   return copy_nodes( src, dst, 1, src_offset, dst_offset );
00722 }
00723 
00724 ErrorCode 
00725 HigherOrderFactory::zero_mid_volume_nodes( ElementSequence* dst )
00726 {
00727   if (!dst->has_mid_volume_nodes())
00728     return MB_FAILURE;
00729   
00730   unsigned dst_offset = CN::VerticesPerEntity( dst->type() );
00731   if (dst->has_mid_edge_nodes())
00732     dst_offset += CN::NumSubEntities( dst->type(), 1 );
00733   if (dst->has_mid_face_nodes())
00734     dst_offset += CN::NumSubEntities( dst->type(), 2 );
00735   return zero_nodes( dst, 1, dst_offset );
00736 }
00737 
00738 ErrorCode 
00739 HigherOrderFactory::copy_nodes( ElementSequence* src,
00740                                 ElementSequence* dst,
00741                                 unsigned nodes_per_elem,
00742                                 unsigned src_offset,
00743                                 unsigned dst_offset )
00744 {
00745   if (src->type() != dst->type())
00746     return MB_FAILURE;
00747 
00748   unsigned src_stride = src->nodes_per_element();
00749   unsigned dst_stride = dst->nodes_per_element();
00750   EntityHandle* src_conn = src->get_connectivity_array();
00751   EntityHandle* dst_conn = dst->get_connectivity_array();
00752   if (!src_conn || !dst_conn)
00753     return MB_FAILURE;
00754   
00755   if (dst->start_handle() < src->start_handle() ||
00756       dst->end_handle()   > src->end_handle())
00757     return MB_FAILURE;
00758   
00759   src_conn += (dst->start_handle() - src->start_handle()) * src_stride;
00760   EntityID count = dst->size();
00761   for (EntityID i = 0; i < count; ++i) {
00762     for (unsigned j = 0; j < nodes_per_elem; ++j)
00763       dst_conn[j+dst_offset] = src_conn[j+src_offset];
00764     src_conn += src_stride; 
00765     dst_conn += dst_stride;
00766   }
00767   
00768   return MB_SUCCESS;
00769 }
00770 
00771 ErrorCode 
00772 HigherOrderFactory::zero_nodes(ElementSequence* dst,
00773                                 unsigned nodes_per_elem,
00774                                 unsigned offset )
00775 {
00776   unsigned dst_stride = dst->nodes_per_element();
00777   EntityHandle* dst_conn = dst->get_connectivity_array();
00778   if (!dst_conn)
00779     return MB_FAILURE;
00780   
00781   EntityID count = dst->size();
00782   for (EntityID i = 0; i < count; ++i) {
00783     std::fill( dst_conn + offset, dst_conn + offset + nodes_per_elem, 0 );
00784     dst_conn += dst_stride;
00785   }
00786   
00787   return MB_SUCCESS;
00788 }
00789 
00790 ErrorCode 
00791 HigherOrderFactory::remove_mid_edge_nodes( ElementSequence* seq, 
00792                                            EntityHandle start,
00793                                            EntityHandle end,
00794                                            Tag deletable_nodes )
00795 {
00796   int count;
00797   int offset;
00798   if (seq->type() == MBEDGE) {
00799     count = 1;
00800     offset = 2;
00801   }
00802   else {
00803     count = CN::NumSubEntities( seq->type(), 1 );
00804     offset = CN::VerticesPerEntity( seq->type() );
00805   }
00806   
00807   return remove_ho_nodes( seq, start, end, count, offset, deletable_nodes );
00808 }
00809 
00810 
00811 ErrorCode 
00812 HigherOrderFactory::remove_mid_face_nodes( ElementSequence* seq, 
00813                                            EntityHandle start,
00814                                            EntityHandle end,
00815                                            Tag deletable_nodes )
00816 {
00817   int count;
00818   if (CN::Dimension(seq->type()) == 2)
00819     count = 1;
00820   else 
00821     count = CN::NumSubEntities( seq->type(), 2 );
00822   int offset = CN::VerticesPerEntity( seq->type() );
00823   if (seq->has_mid_edge_nodes())
00824     offset += CN::NumSubEntities( seq->type(), 1 );
00825   
00826   return remove_ho_nodes( seq, start, end, count, offset, deletable_nodes );
00827 }
00828 
00829 ErrorCode 
00830 HigherOrderFactory::remove_mid_volume_nodes( ElementSequence* seq, 
00831                                              EntityHandle start,
00832                                              EntityHandle end,
00833                                              Tag deletable_nodes )
00834 {
00835   int offset = CN::VerticesPerEntity( seq->type() );
00836   if (seq->has_mid_edge_nodes())
00837     offset += CN::NumSubEntities( seq->type(), 1 );
00838   if (seq->has_mid_face_nodes())
00839     offset += CN::NumSubEntities( seq->type(), 2 );
00840   
00841   return remove_ho_nodes( seq, start, end, 1, offset, deletable_nodes );
00842 }
00843 
00844 // Code mostly copied from old EntitySequence.cpp
00845 // (ElementEntitySequence::convert_realloc & 
00846 //  ElementEntitySequence::tag_for_deletion).
00847 // Copyright from old EntitySequence.cpp:
00862 ErrorCode 
00863 HigherOrderFactory::remove_ho_nodes( ElementSequence* seq,
00864                                      EntityHandle start,
00865                                      EntityHandle end,
00866                                      int nodes_per_elem,
00867                                      int elem_conn_offset,
00868                                      Tag deletable_nodes )
00869 {
00870   if (start < seq->start_handle() || end > seq->end_handle())
00871     return MB_ENTITY_NOT_FOUND;
00872   EntityHandle* array = seq->get_connectivity_array();
00873   if (!array)
00874     return MB_NOT_IMPLEMENTED;
00875    
00876   std::set<EntityHandle> nodes_processed;
00877   for (EntityHandle i = start; i <= end; ++i) {  // for each element
00878     for (int j = 0; j < nodes_per_elem; ++j) {  // for each HO node to remove
00879       const EntityID elem = (i - seq->start_handle()); // element index
00880       const int conn_idx = j + elem_conn_offset;
00881       const EntityID index = elem * seq->nodes_per_element() + conn_idx;
00882       if (array[index] && nodes_processed.insert( array[index] ).second) {
00883         if (tag_for_deletion( i, conn_idx, seq )) {
00884           unsigned char bit = 0x1;
00885           mMB->tag_set_data( deletable_nodes, &(array[index]), 1, &bit );
00886         }
00887       }
00888     }
00889   }
00890   
00891   return MB_SUCCESS;
00892 }
00893 
00894 bool
00895 HigherOrderFactory::tag_for_deletion( EntityHandle parent_handle,
00896                                       int conn_index,
00897                                       ElementSequence* seq )
00898 {
00899   //get type of this sequence
00900   EntityType this_type = seq->type();
00901 
00902   //get dimension of 'parent' element
00903   int this_dimension = mMB->dimension_from_handle( parent_handle );
00904 
00905   //tells us if higher order node is on 
00906   int dimension, side_number; 
00907   CN::HONodeParent( this_type, seq->nodes_per_element(),
00908                       conn_index, dimension, side_number );  
00909 
00910   //it MUST be a higher-order node
00911   bool delete_node = false;
00912 
00913   assert( dimension != -1 );
00914   assert( side_number != -1 );
00915 
00916   //could be a mid-volume/face/edge node on a hex/face/edge respectively
00917   //if so...delete it bc/ no one else owns it too
00918   std::vector<EntityHandle> connectivity;
00919   if( dimension == this_dimension && side_number == 0 )
00920     delete_node = true;
00921   else //the node could also be on a lower order entity of 'tmp_entity' 
00922   {
00923     //get 'side' of 'parent_handle' that node is on 
00924     EntityHandle target_entity = 0;
00925     mMB->side_element( parent_handle, dimension, side_number, target_entity );
00926 
00927     if( target_entity )
00928     {
00929       AEntityFactory *a_fact = mMB->a_entity_factory();
00930       EntityHandle low_meshset;
00931       int dum;
00932       low_meshset = CREATE_HANDLE(MBENTITYSET, 0, dum);
00933 
00934       //just get corner nodes of target_entity
00935       connectivity.clear();
00936       mMB->get_connectivity(&( target_entity), 1, connectivity, true  );
00937 
00938       //for each node, get all common adjacencies of nodes in 'parent_handle' 
00939       std::vector<EntityHandle> adj_list_1, adj_list_2, adj_entities;
00940       a_fact->get_adjacencies(connectivity[0], adj_list_1);
00941 
00942       // remove meshsets
00943       adj_list_1.erase(std::remove_if(adj_list_1.begin(), adj_list_1.end(), 
00944            std::bind2nd(std::greater<EntityHandle>(),low_meshset)), adj_list_1.end());
00945 
00946       size_t i; 
00947       for( i=1; i<connectivity.size(); i++)
00948       {
00949         adj_list_2.clear();
00950         a_fact->get_adjacencies(connectivity[i], adj_list_2);
00951 
00952         // remove meshsets
00953         adj_list_2.erase(std::remove_if(adj_list_2.begin(), adj_list_2.end(), 
00954              std::bind2nd(std::greater<EntityHandle>(),low_meshset)), adj_list_2.end());
00955        
00956         //intersect the 2 lists 
00957         adj_entities.clear();
00958         std::set_intersection(adj_list_1.begin(), adj_list_1.end(), 
00959                               adj_list_2.begin(), adj_list_2.end(), 
00960                               std::back_inserter< std::vector<EntityHandle> >(adj_entities));
00961         adj_list_1.clear();
00962         adj_list_1 = adj_entities;
00963       } 
00964 
00965       assert( adj_entities.size() );  //has to have at least one adjacency 
00966 
00967       //see if node is in other elements, not in this sequence...if so, delete it 
00968       for( i=0; i<adj_entities.size(); i++)
00969       {
00970         if( adj_entities[i] >= seq->start_handle() &&
00971             adj_entities[i] <= seq->end_handle() )
00972         {
00973           delete_node = false;
00974           break;
00975         }
00976         else 
00977           delete_node = true;
00978       }             
00979     }
00980     else //there is no lower order entity that also contains node 
00981       delete_node = true;
00982   }
00983 
00984   return delete_node;
00985 }
00986   
00987 } // namespace moab
00988 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines