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