![]() |
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
00032 #include
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(),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(),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