moab
|
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