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 #include "moab/CN.hpp" 00017 #include "MBCNArrays.hpp" 00018 #include "MBCN.h" 00019 #include <cassert> 00020 #include <cstring> 00021 #include <iterator> 00022 00023 namespace moab 00024 { 00025 00026 const char* CN::entityTypeNames[] = { "Vertex", "Edge", "Tri", "Quad", "Polygon", "Tet", "Pyramid", 00027 "Prism", "Knife", "Hex", "Polyhedron", "EntitySet", "MaxType" }; 00028 00029 short int CN::numberBasis = 0; 00030 00031 short int CN::permuteVec[MBMAXTYPE][3][MAX_SUB_ENTITIES + 1]; 00032 short int CN::revPermuteVec[MBMAXTYPE][3][MAX_SUB_ENTITIES + 1]; 00033 00034 const DimensionPair CN::TypeDimensionMap[] = { 00035 DimensionPair( MBVERTEX, MBVERTEX ), DimensionPair( MBEDGE, MBEDGE ), 00036 DimensionPair( MBTRI, MBPOLYGON ), DimensionPair( MBTET, MBPOLYHEDRON ), 00037 DimensionPair( MBENTITYSET, MBENTITYSET ), DimensionPair( MBMAXTYPE, MBMAXTYPE ) }; 00038 00039 short CN::increasingInts[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 00040 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39 }; 00041 00042 //! set the basis of the numbering system; may or may not do things besides setting the 00043 //! member variable 00044 void CN::SetBasis( const int in_basis ) 00045 { 00046 numberBasis = in_basis; 00047 } 00048 00049 /// Get the dimension pair corresponding to a dimension 00050 DimensionPair CN::getDimPair( int entity_type ) 00051 { 00052 return TypeDimensionMap[entity_type]; 00053 } 00054 00055 //! return a type for the given name 00056 EntityType CN::EntityTypeFromName( const char* name ) 00057 { 00058 for( EntityType i = MBVERTEX; i < MBMAXTYPE; i++ ) 00059 { 00060 if( 0 == strcmp( name, entityTypeNames[i] ) ) return i; 00061 } 00062 00063 return MBMAXTYPE; 00064 } 00065 00066 void CN::SubEntityNodeIndices( const EntityType this_topo, 00067 const int num_nodes, 00068 const int sub_dimension, 00069 const int sub_index, 00070 EntityType& subentity_topo, 00071 int& num_sub_entity_nodes, 00072 int sub_entity_conn[] ) 00073 { 00074 // If asked for a node, the special case... 00075 if( sub_dimension == 0 ) 00076 { 00077 assert( sub_index < num_nodes ); 00078 subentity_topo = MBVERTEX; 00079 num_sub_entity_nodes = 1; 00080 sub_entity_conn[0] = sub_index; 00081 return; 00082 } 00083 00084 const int ho_bits = HasMidNodes( this_topo, num_nodes ); 00085 subentity_topo = SubEntityType( this_topo, sub_dimension, sub_index ); 00086 num_sub_entity_nodes = VerticesPerEntity( subentity_topo ); 00087 const short* corners = mConnectivityMap[this_topo][sub_dimension - 1].conn[sub_index]; 00088 std::copy( corners, corners + num_sub_entity_nodes, sub_entity_conn ); 00089 00090 int sub_sub_corners[MAX_SUB_ENTITY_VERTICES]; 00091 int side, sense, offset; 00092 for( int dim = 1; dim <= sub_dimension; ++dim ) 00093 { 00094 if( !( ho_bits & ( 1 << dim ) ) ) continue; 00095 00096 const short num_mid = NumSubEntities( subentity_topo, dim ); 00097 for( int i = 0; i < num_mid; ++i ) 00098 { 00099 const EntityType sub_sub_topo = SubEntityType( subentity_topo, dim, i ); 00100 const int sub_sub_num_vert = VerticesPerEntity( sub_sub_topo ); 00101 SubEntityVertexIndices( subentity_topo, dim, i, sub_sub_corners ); 00102 00103 for( int j = 0; j < sub_sub_num_vert; ++j ) 00104 sub_sub_corners[j] = corners[sub_sub_corners[j]]; 00105 SideNumber( this_topo, sub_sub_corners, sub_sub_num_vert, dim, side, sense, offset ); 00106 sub_entity_conn[num_sub_entity_nodes++] = HONodeIndex( this_topo, num_nodes, dim, side ); 00107 } 00108 } 00109 } 00110 00111 //! return the vertices of the specified sub entity 00112 //! \param parent_conn Connectivity of parent entity 00113 //! \param parent_type Entity type of parent entity 00114 //! \param sub_dimension Dimension of sub-entity being queried 00115 //! \param sub_index Index of sub-entity being queried 00116 //! \param sub_entity_conn Connectivity of sub-entity, based on parent_conn and canonical 00117 //! ordering for parent_type 00118 //! \param num_sub_vertices Number of vertices in sub-entity 00119 void CN::SubEntityConn( const void* parent_conn, 00120 const EntityType parent_type, 00121 const int sub_dimension, 00122 const int sub_index, 00123 void* sub_entity_conn, 00124 int& num_sub_vertices ) 00125 { 00126 static int sub_indices[MAX_SUB_ENTITY_VERTICES]; 00127 00128 SubEntityVertexIndices( parent_type, sub_dimension, sub_index, sub_indices ); 00129 00130 num_sub_vertices = VerticesPerEntity( SubEntityType( parent_type, sub_dimension, sub_index ) ); 00131 void** parent_conn_ptr = static_cast< void** >( const_cast< void* >( parent_conn ) ); 00132 void** sub_conn_ptr = static_cast< void** >( sub_entity_conn ); 00133 for( int i = 0; i < num_sub_vertices; i++ ) 00134 sub_conn_ptr[i] = parent_conn_ptr[sub_indices[i]]; 00135 } 00136 00137 //! given an entity and a target dimension & side number, get that entity 00138 short int CN::AdjacentSubEntities( const EntityType this_type, 00139 const int* source_indices, 00140 const int num_source_indices, 00141 const int source_dim, 00142 const int target_dim, 00143 std::vector< int >& index_list, 00144 const int operation_type ) 00145 { 00146 // first get all the vertex indices 00147 std::vector< int > tmp_indices; 00148 const int* it1 = source_indices; 00149 00150 assert( source_dim <= 3 && target_dim >= 0 && target_dim <= 3 && 00151 // make sure we're not stepping off the end of the array; 00152 ( ( source_dim > 0 && *it1 < mConnectivityMap[this_type][source_dim - 1].num_sub_elements ) || 00153 ( source_dim == 0 && 00154 *it1 < mConnectivityMap[this_type][Dimension( this_type ) - 1].num_corners_per_sub_element[0] ) ) && 00155 *it1 >= 0 ); 00156 00157 #define MUC CN::mUpConnMap[this_type][source_dim][target_dim] 00158 00159 // if we're looking for the vertices of a single side, return them in 00160 // the canonical ordering; otherwise, return them in sorted order 00161 if( num_source_indices == 1 && 0 == target_dim && source_dim != target_dim ) 00162 { 00163 00164 // element of mConnectivityMap should be for this type and for one 00165 // less than source_dim, which should give the connectivity of that sub element 00166 const ConnMap& cm = mConnectivityMap[this_type][source_dim - 1]; 00167 std::copy( cm.conn[source_indices[0]], 00168 cm.conn[source_indices[0]] + cm.num_corners_per_sub_element[source_indices[0]], 00169 std::back_inserter( index_list ) ); 00170 return 0; 00171 } 00172 00173 // now go through source indices, folding adjacencies into target list 00174 for( it1 = source_indices; it1 != source_indices + num_source_indices; it1++ ) 00175 { 00176 // *it1 is the side index 00177 // at start of iteration, index_list has the target list 00178 00179 // if a union, or first iteration and index list was empty, copy the list 00180 if( operation_type == CN::UNION || ( it1 == source_indices && index_list.empty() ) ) 00181 { 00182 std::copy( MUC.targets_per_source_element[*it1], 00183 MUC.targets_per_source_element[*it1] + MUC.num_targets_per_source_element[*it1], 00184 std::back_inserter( index_list ) ); 00185 } 00186 else 00187 { 00188 // else we're intersecting, and have a non-empty list; intersect with this target list 00189 tmp_indices.clear(); 00190 for( int i = MUC.num_targets_per_source_element[*it1] - 1; i >= 0; i-- ) 00191 if( std::find( index_list.begin(), index_list.end(), MUC.targets_per_source_element[*it1][i] ) != 00192 index_list.end() ) 00193 tmp_indices.push_back( MUC.targets_per_source_element[*it1][i] ); 00194 // std::set_intersection(MUC.targets_per_source_element[*it1], 00195 // MUC.targets_per_source_element[*it1]+ 00196 // MUC.num_targets_per_source_element[*it1], 00197 // index_list.begin(), index_list.end(), 00198 // std::back_inserter(tmp_indices)); 00199 index_list.swap( tmp_indices ); 00200 00201 // if we're at this point and the list is empty, the intersection will be NULL; 00202 // return if so 00203 if( index_list.empty() ) return 0; 00204 } 00205 } 00206 00207 if( operation_type == CN::UNION && num_source_indices != 1 ) 00208 { 00209 // need to sort then unique the list 00210 std::sort( index_list.begin(), index_list.end() ); 00211 index_list.erase( std::unique( index_list.begin(), index_list.end() ), index_list.end() ); 00212 } 00213 00214 return 0; 00215 } 00216 00217 template < typename T > 00218 static short int side_number( const T* parent_conn, 00219 const EntityType parent_type, 00220 const T* child_conn, 00221 const int child_num_verts, 00222 const int child_dim, 00223 int& side_no, 00224 int& sense, 00225 int& offset ) 00226 { 00227 int parent_num_verts = CN::VerticesPerEntity( parent_type ); 00228 int side_indices[8]; 00229 assert( sizeof( side_indices ) / sizeof( side_indices[0] ) >= (size_t)child_num_verts ); 00230 00231 for( int i = 0; i < child_num_verts; i++ ) 00232 { 00233 side_indices[i] = std::find( parent_conn, parent_conn + parent_num_verts, child_conn[i] ) - parent_conn; 00234 if( side_indices[i] == parent_num_verts ) return -1; 00235 } 00236 00237 return CN::SideNumber( parent_type, &side_indices[0], child_num_verts, child_dim, side_no, sense, offset ); 00238 } 00239 00240 short int CN::SideNumber( const EntityType parent_type, 00241 const int* parent_conn, 00242 const int* child_conn, 00243 const int child_num_verts, 00244 const int child_dim, 00245 int& side_no, 00246 int& sense, 00247 int& offset ) 00248 { 00249 return side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, side_no, sense, offset ); 00250 } 00251 00252 short int CN::SideNumber( const EntityType parent_type, 00253 const unsigned int* parent_conn, 00254 const unsigned int* child_conn, 00255 const int child_num_verts, 00256 const int child_dim, 00257 int& side_no, 00258 int& sense, 00259 int& offset ) 00260 { 00261 return side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, side_no, sense, offset ); 00262 } 00263 short int CN::SideNumber( const EntityType parent_type, 00264 const long* parent_conn, 00265 const long* child_conn, 00266 const int child_num_verts, 00267 const int child_dim, 00268 int& side_no, 00269 int& sense, 00270 int& offset ) 00271 { 00272 return side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, side_no, sense, offset ); 00273 } 00274 short int CN::SideNumber( const EntityType parent_type, 00275 const unsigned long* parent_conn, 00276 const unsigned long* child_conn, 00277 const int child_num_verts, 00278 const int child_dim, 00279 int& side_no, 00280 int& sense, 00281 int& offset ) 00282 { 00283 return side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, side_no, sense, offset ); 00284 } 00285 00286 short int CN::SideNumber( const EntityType parent_type, 00287 const unsigned long long* parent_conn, 00288 const unsigned long long* child_conn, 00289 const int child_num_verts, 00290 const int child_dim, 00291 int& side_no, 00292 int& sense, 00293 int& offset ) 00294 00295 { 00296 return side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, side_no, sense, offset ); 00297 } 00298 00299 short int CN::SideNumber( const EntityType parent_type, 00300 void* const* parent_conn, 00301 void* const* child_conn, 00302 const int child_num_verts, 00303 const int child_dim, 00304 int& side_no, 00305 int& sense, 00306 int& offset ) 00307 { 00308 return side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, side_no, sense, offset ); 00309 } 00310 00311 short int CN::SideNumber( const EntityType parent_type, 00312 const int* child_conn_indices, 00313 const int child_num_verts, 00314 const int child_dim, 00315 int& side_no, 00316 int& sense, 00317 int& offset ) 00318 { 00319 int parent_dim = Dimension( parent_type ); 00320 int parent_num_verts = VerticesPerEntity( parent_type ); 00321 00322 // degenerate case (vertex), output == input 00323 if( child_dim == 0 ) 00324 { 00325 if( child_num_verts != 1 ) return -1; 00326 side_no = *child_conn_indices; 00327 sense = offset = 0; 00328 } 00329 00330 // given a parent and child element, find the corresponding side number 00331 00332 // dim_diff should be -1, 0 or 1 (same dimension, one less dimension, two less, resp.) 00333 if( child_dim > parent_dim || child_dim < 0 ) return -1; 00334 00335 // different types of same dimension won't be the same 00336 if( parent_dim == child_dim && parent_num_verts != child_num_verts ) 00337 { 00338 side_no = -1; 00339 sense = 0; 00340 return 0; 00341 } 00342 00343 // loop over the sub-elements, comparing to child connectivity 00344 int sub_conn_indices[10]; 00345 for( int i = 0; i < NumSubEntities( parent_type, child_dim ); i++ ) 00346 { 00347 int sub_size = VerticesPerEntity( SubEntityType( parent_type, child_dim, i ) ); 00348 if( sub_size != child_num_verts ) continue; 00349 00350 SubEntityVertexIndices( parent_type, child_dim, i, sub_conn_indices ); 00351 bool they_match = ConnectivityMatch( child_conn_indices, sub_conn_indices, sub_size, sense, offset ); 00352 if( they_match ) 00353 { 00354 side_no = i; 00355 return 0; 00356 } 00357 } 00358 00359 // if we've gotten here, we don't match 00360 side_no = -1; 00361 00362 // return value is no success 00363 return 1; 00364 } 00365 00366 //! return the dimension and index of the opposite side, given parent entity type and child 00367 //! dimension and index. This function is only defined for certain types of parent/child types: 00368 //! (Parent, Child dim->Opposite dim): 00369 //! (Tri, 1->0), (Tri, 0->1), (Quad, 1->1), (Quad, 0->0), 00370 //! (Tet, 2->0), (Tet, 1->1), (Tet, 0->2), 00371 //! (Hex, 2->2), (Hex, 1->1)(diagonally across element), (Hex, 0->0) (diagonally across element) 00372 //! All other parent types and child dimensions return an error. 00373 //! 00374 //! \param parent_type The type of parent element 00375 //! \param child_type The type of child element 00376 //! \param child_index The index of the child element 00377 //! \param opposite_index The index of the opposite element 00378 //! \return status Returns 0 if successful, -1 if not 00379 short int CN::OppositeSide( const EntityType parent_type, 00380 const int child_index, 00381 const int child_dim, 00382 int& opposite_index, 00383 int& opposite_dim ) 00384 { 00385 switch( parent_type ) 00386 { 00387 case MBEDGE: 00388 if( 0 != child_dim ) 00389 return -1; 00390 else 00391 opposite_index = 1 - child_index; 00392 opposite_dim = 0; 00393 break; 00394 00395 case MBTRI: 00396 switch( child_dim ) 00397 { 00398 case 0: 00399 opposite_dim = 1; 00400 opposite_index = ( child_index + 1 ) % 3; 00401 break; 00402 case 1: 00403 opposite_dim = 0; 00404 opposite_index = ( child_index + 2 ) % 3; 00405 break; 00406 default: 00407 return -1; 00408 } 00409 break; 00410 00411 case MBQUAD: 00412 switch( child_dim ) 00413 { 00414 case 0: 00415 case 1: 00416 opposite_dim = child_dim; 00417 opposite_index = ( child_index + 2 ) % 4; 00418 break; 00419 default: 00420 return -1; 00421 } 00422 break; 00423 00424 case MBTET: 00425 switch( child_dim ) 00426 { 00427 case 0: 00428 opposite_dim = 2; 00429 opposite_index = ( child_index + 1 ) % 3 + 2 * ( child_index / 3 ); 00430 break; 00431 case 1: 00432 opposite_dim = 1; 00433 opposite_index = child_index < 3 ? 3 + ( child_index + 2 ) % 3 : ( child_index + 1 ) % 3; 00434 break; 00435 case 2: 00436 opposite_dim = 0; 00437 opposite_index = ( child_index + 2 ) % 3 + child_index / 3; 00438 break; 00439 default: 00440 return -1; 00441 } 00442 break; 00443 case MBHEX: 00444 opposite_dim = child_dim; 00445 switch( child_dim ) 00446 { 00447 case 0: 00448 opposite_index = child_index < 4 ? 4 + ( child_index + 2 ) % 4 : ( child_index - 2 ) % 4; 00449 break; 00450 case 1: 00451 opposite_index = 4 * ( 2 - child_index / 4 ) + ( child_index + 2 ) % 4; 00452 break; 00453 case 2: 00454 opposite_index = child_index < 4 ? ( child_index + 2 ) % 4 : 9 - child_index; 00455 break; 00456 default: 00457 return -1; 00458 } 00459 break; 00460 00461 default: 00462 return -1; 00463 } 00464 00465 return 0; 00466 } 00467 00468 template < typename T > 00469 inline bool connectivity_match( const T* conn1_i, const T* conn2_i, const int num_vertices, int& direct, int& offset ) 00470 { 00471 00472 bool they_match; 00473 00474 // special test for 2 handles, since we don't want to wrap the list in this 00475 // case 00476 if( num_vertices == 2 ) 00477 { 00478 they_match = false; 00479 if( conn1_i[0] == conn2_i[0] && conn1_i[1] == conn2_i[1] ) 00480 { 00481 direct = 1; 00482 they_match = true; 00483 offset = 0; 00484 } 00485 else if( conn1_i[0] == conn2_i[1] && conn1_i[1] == conn2_i[0] ) 00486 { 00487 they_match = true; 00488 direct = -1; 00489 offset = 1; 00490 } 00491 } 00492 00493 else 00494 { 00495 const T* iter; 00496 iter = std::find( &conn2_i[0], &conn2_i[num_vertices], conn1_i[0] ); 00497 if( iter == &conn2_i[num_vertices] ) return false; 00498 00499 they_match = true; 00500 00501 offset = iter - conn2_i; 00502 int i; 00503 00504 // first compare forward 00505 for( i = 1; i < num_vertices; ++i ) 00506 { 00507 if( conn1_i[i] != conn2_i[( offset + i ) % num_vertices] ) 00508 { 00509 they_match = false; 00510 break; 00511 } 00512 } 00513 00514 if( they_match == true ) 00515 { 00516 direct = 1; 00517 return they_match; 00518 } 00519 00520 they_match = true; 00521 00522 // then compare reverse 00523 for( i = 1; i < num_vertices; i++ ) 00524 { 00525 if( conn1_i[i] != conn2_i[( offset + num_vertices - i ) % num_vertices] ) 00526 { 00527 they_match = false; 00528 break; 00529 } 00530 } 00531 if( they_match ) 00532 { 00533 direct = -1; 00534 } 00535 } 00536 00537 return they_match; 00538 } 00539 00540 bool CN::ConnectivityMatch( const int* conn1_i, const int* conn2_i, const int num_vertices, int& direct, int& offset ) 00541 { 00542 return connectivity_match< int >( conn1_i, conn2_i, num_vertices, direct, offset ); 00543 } 00544 00545 bool CN::ConnectivityMatch( const unsigned int* conn1_i, 00546 const unsigned int* conn2_i, 00547 const int num_vertices, 00548 int& direct, 00549 int& offset ) 00550 { 00551 return connectivity_match< unsigned int >( conn1_i, conn2_i, num_vertices, direct, offset ); 00552 } 00553 00554 bool CN::ConnectivityMatch( const long* conn1_i, const long* conn2_i, const int num_vertices, int& direct, int& offset ) 00555 { 00556 return connectivity_match< long >( conn1_i, conn2_i, num_vertices, direct, offset ); 00557 } 00558 00559 bool CN::ConnectivityMatch( const unsigned long* conn1_i, 00560 const unsigned long* conn2_i, 00561 const int num_vertices, 00562 int& direct, 00563 int& offset ) 00564 { 00565 return connectivity_match< unsigned long >( conn1_i, conn2_i, num_vertices, direct, offset ); 00566 } 00567 00568 bool CN::ConnectivityMatch( const unsigned long long* conn1_i, 00569 const unsigned long long* conn2_i, 00570 const int num_vertices, 00571 int& direct, 00572 int& offset ) 00573 { 00574 return connectivity_match< unsigned long long >( conn1_i, conn2_i, num_vertices, direct, offset ); 00575 } 00576 00577 bool CN::ConnectivityMatch( void* const* conn1_i, 00578 void* const* conn2_i, 00579 const int num_vertices, 00580 int& direct, 00581 int& offset ) 00582 { 00583 return connectivity_match< void* >( conn1_i, conn2_i, num_vertices, direct, offset ); 00584 } 00585 00586 //! for an entity of this type and a specified subfacet (dimension and index), return 00587 //! the index of the higher order node for that entity in this entity's connectivity array 00588 short int CN::HONodeIndex( const EntityType this_type, 00589 const int num_verts, 00590 const int subfacet_dim, 00591 const int subfacet_index ) 00592 { 00593 int i; 00594 int has_mids[4]; 00595 HasMidNodes( this_type, num_verts, has_mids ); 00596 00597 // if we have no mid nodes on the subfacet_dim, we have no index 00598 if( subfacet_index != -1 && !has_mids[subfacet_dim] ) return -1; 00599 00600 // put start index at last index (one less than the number of vertices 00601 // plus the index basis) 00602 int index = VerticesPerEntity( this_type ) - 1 + numberBasis; 00603 00604 // for each subfacet dimension less than the target subfacet dim which has mid nodes, 00605 // add the number of subfacets of that dimension to the index 00606 for( i = 1; i < subfacet_dim; i++ ) 00607 if( has_mids[i] ) index += NumSubEntities( this_type, i ); 00608 00609 // now add the index of this subfacet, or one if we're asking about the entity as a whole 00610 if( subfacet_index == -1 && has_mids[subfacet_dim] ) 00611 // want the index of the last ho node on this subfacet 00612 index += NumSubEntities( this_type, subfacet_dim ); 00613 00614 else if( subfacet_index != -1 && has_mids[subfacet_dim] ) 00615 index += subfacet_index + 1 - numberBasis; 00616 00617 // that's it 00618 return index; 00619 } 00620 00621 //! given data about an element and a vertex in that element, return the dimension 00622 //! and index of the sub-entity that the vertex resolves. If it does not resolve a 00623 //! sub-entity, either because it's a corner node or it's not in the element, -1 is 00624 //! returned in both return values 00625 void CN::HONodeParent( EntityType elem_type, int num_verts, int ho_index, int& parent_dim, int& parent_index ) 00626 { 00627 // begin with error values 00628 parent_dim = parent_index = -1; 00629 00630 // given the number of verts and the element type, get the hasmidnodes solution 00631 int has_mids[4]; 00632 HasMidNodes( elem_type, num_verts, has_mids ); 00633 00634 int index = VerticesPerEntity( elem_type ) - 1; 00635 const int dim = Dimension( elem_type ); 00636 00637 // keep a running sum of the ho node indices for this type of element, and stop 00638 // when you get to the dimension which has the ho node 00639 for( int i = 1; i < dim; i++ ) 00640 { 00641 if( has_mids[i] ) 00642 { 00643 if( ho_index <= index + NumSubEntities( elem_type, i ) ) 00644 { 00645 // the ho_index resolves an entity of dimension i, so set the return values 00646 // and break out of the loop 00647 parent_dim = i; 00648 parent_index = ho_index - index - 1; 00649 return; 00650 } 00651 else 00652 { 00653 index += NumSubEntities( elem_type, i ); 00654 } 00655 } 00656 } 00657 00658 // mid region node case 00659 if( has_mids[dim] && ho_index == index + 1 ) 00660 { 00661 parent_dim = dim; 00662 parent_index = 0; 00663 } 00664 } 00665 00666 const char* CN::EntityTypeName( const EntityType this_type ) 00667 { 00668 return entityTypeNames[this_type]; 00669 } 00670 00671 } // namespace moab 00672 00673 using moab::CN; 00674 using moab::EntityType; 00675 00676 //! get the basis of the numbering system 00677 void MBCN_GetBasis( int* rval ) 00678 { 00679 *rval = CN::GetBasis(); 00680 } 00681 00682 //! set the basis of the numbering system 00683 void MBCN_SetBasis( const int in_basis ) 00684 { 00685 CN::SetBasis( in_basis ); 00686 } 00687 00688 //! return the string type name for this type 00689 void MBCN_EntityTypeName( const int this_type, char* rval, int rval_len ) 00690 { 00691 const char* rval_tmp = CN::EntityTypeName( (EntityType)this_type ); 00692 int rval_len_tmp = strlen( rval_tmp ); 00693 rval_len_tmp = ( rval_len_tmp < rval_len ? rval_len_tmp : rval_len ); 00694 strncpy( rval, rval_tmp, rval_len_tmp ); 00695 } 00696 00697 //! given a name, find the corresponding entity type 00698 void MBCN_EntityTypeFromName( const char* name, int* rval ) 00699 { 00700 *rval = CN::EntityTypeFromName( name ); 00701 } 00702 00703 //! return the topological entity dimension 00704 void MBCN_Dimension( const int t, int* rval ) 00705 { 00706 *rval = CN::Dimension( (EntityType)t ); 00707 } 00708 00709 //! return the number of (corner) vertices contained in the specified type. 00710 void MBCN_VerticesPerEntity( const int t, int* rval ) 00711 { 00712 *rval = CN::VerticesPerEntity( (EntityType)t ); 00713 } 00714 00715 //! return the number of sub-entities bounding the entity. 00716 void MBCN_NumSubEntities( const int t, const int d, int* rval ) 00717 { 00718 *rval = CN::NumSubEntities( (EntityType)t, d ); 00719 } 00720 00721 //! return the type of a particular sub-entity. 00722 //! \param this_type Type of entity for which sub-entity type is being queried 00723 //! \param sub_dimension Topological dimension of sub-entity whose type is being queried 00724 //! \param index Index of sub-entity whose type is being queried 00725 //! \return type Entity type of sub-entity with specified dimension and index 00726 void MBCN_SubEntityType( const int this_type, const int sub_dimension, const int index, int* rval ) 00727 00728 { 00729 00730 *rval = CN::SubEntityType( (EntityType)this_type, sub_dimension, index ); 00731 } 00732 00733 //! return the vertex indices of the specified sub-entity. 00734 //! \param this_type Type of entity for which sub-entity connectivity is being queried 00735 //! \param sub_dimension Dimension of sub-entity 00736 //! \param sub_index Index of sub-entity 00737 //! \param sub_entity_conn Connectivity of sub-entity (returned to calling function) 00738 void MBCN_SubEntityVertexIndices( const int this_type, 00739 const int sub_dimension, 00740 const int sub_index, 00741 int sub_entity_conn[] ) 00742 { 00743 CN::SubEntityVertexIndices( (EntityType)this_type, sub_dimension, sub_index, sub_entity_conn ); 00744 } 00745 00746 //! return the vertices of the specified sub entity 00747 //! \param parent_conn Connectivity of parent entity 00748 //! \param parent_type Entity type of parent entity 00749 //! \param sub_dimension Dimension of sub-entity being queried 00750 //! \param sub_index Index of sub-entity being queried 00751 //! \param sub_entity_conn Connectivity of sub-entity, based on parent_conn and canonical 00752 //! ordering for parent_type 00753 //! \param num_sub_vertices Number of vertices in sub-entity 00754 // void MBCN_SubEntityConn(const void *parent_conn, const int parent_type, 00755 // const int sub_dimension, 00756 // const int sub_index, 00757 // void *sub_entity_conn, int &num_sub_vertices) {return 00758 // CN::SubEntityConn();} 00759 00760 //! For a specified set of sides of given dimension, return the intersection 00761 //! or union of all sides of specified target dimension adjacent to those sides. 00762 //! \param this_type Type of entity for which sub-entity connectivity is being queried 00763 //! \param source_indices Indices of sides being queried 00764 //! \param num_source_indices Number of entries in <em>source_indices</em> 00765 //! \param source_dim Dimension of source entity 00766 //! \param target_dim Dimension of target entity 00767 //! \param index_list Indices of target entities (returned) 00768 //! \param num_indices Number of indices of target entities (returned) 00769 //! \param operation_type Specify either CN::INTERSECT (0) or CN::UNION (1) to get intersection 00770 //! or union of target entity lists over source entities 00771 //! \param rval Error code indicating success or failure (returned) 00772 void MBCN_AdjacentSubEntities( const int this_type, 00773 const int* source_indices, 00774 const int num_source_indices, 00775 const int source_dim, 00776 const int target_dim, 00777 int* index_list, 00778 int* num_indices, 00779 const int operation_type, 00780 int* rval ) 00781 { 00782 std::vector< int > tmp_index_list; 00783 *rval = CN::AdjacentSubEntities( (EntityType)this_type, source_indices, num_source_indices, source_dim, target_dim, 00784 tmp_index_list, operation_type ); 00785 std::copy( tmp_index_list.begin(), tmp_index_list.end(), index_list ); 00786 *num_indices = tmp_index_list.size(); 00787 } 00788 00789 //! return the side index represented in the input sub-entity connectivity 00790 //! \param parent_type Entity type of parent entity 00791 //! \param child_conn_indices Child connectivity to query, specified as indices 00792 //! into the connectivity list of the parent. 00793 //! \param child_num_verts Number of values in <em>child_conn_indices</em> 00794 //! \param child_dim Dimension of child entity being queried 00795 //! \param side_no Side number of child entity (returned) 00796 //! \param sense Sense of child entity with respect to order in <em>child_conn</em> (returned) 00797 //! \param offset Offset of <em>child_conn</em> with respect to canonical ordering data (returned) 00798 //! \return status Returns zero if successful, -1 if not 00799 void MBCN_SideNumber( const int parent_type, 00800 const int* child_conn_indices, 00801 const int child_num_verts, 00802 const int child_dim, 00803 int* side_no, 00804 int* sense, 00805 int* offset ) 00806 { 00807 CN::SideNumber( (EntityType)parent_type, child_conn_indices, child_num_verts, child_dim, *side_no, *sense, 00808 *offset ); 00809 } 00810 00811 void MBCN_SideNumberInt( const int* parent_conn, 00812 const EntityType parent_type, 00813 const int* child_conn, 00814 const int child_num_verts, 00815 const int child_dim, 00816 int* side_no, 00817 int* sense, 00818 int* offset ) 00819 { 00820 moab::side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, *side_no, *sense, *offset ); 00821 } 00822 00823 void MBCN_SideNumberUint( const unsigned int* parent_conn, 00824 const EntityType parent_type, 00825 const unsigned int* child_conn, 00826 const int child_num_verts, 00827 const int child_dim, 00828 int* side_no, 00829 int* sense, 00830 int* offset ) 00831 { 00832 moab::side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, *side_no, *sense, *offset ); 00833 } 00834 00835 void MBCN_SideNumberLong( const long* parent_conn, 00836 const EntityType parent_type, 00837 const long* child_conn, 00838 const int child_num_verts, 00839 const int child_dim, 00840 int* side_no, 00841 int* sense, 00842 int* offset ) 00843 { 00844 moab::side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, *side_no, *sense, *offset ); 00845 } 00846 00847 void MBCN_SideNumberUlong( const unsigned long* parent_conn, 00848 const EntityType parent_type, 00849 const unsigned long* child_conn, 00850 const int child_num_verts, 00851 const int child_dim, 00852 int* side_no, 00853 int* sense, 00854 int* offset ) 00855 { 00856 moab::side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, *side_no, *sense, *offset ); 00857 } 00858 00859 void MBCN_SideNumberVoid( void* const* parent_conn, 00860 const EntityType parent_type, 00861 void* const* child_conn, 00862 const int child_num_verts, 00863 const int child_dim, 00864 int* side_no, 00865 int* sense, 00866 int* offset ) 00867 { 00868 moab::side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, *side_no, *sense, *offset ); 00869 } 00870 00871 //! return the dimension and index of the opposite side, given parent entity type and child 00872 //! dimension and index. This function is only defined for certain types of parent/child types: 00873 //! (Parent, Child dim->Opposite dim): 00874 //! (Tri, 1->0), (Tri, 0->1), (Quad, 1->1), (Quad, 0->0), 00875 //! (Tet, 2->0), (Tet, 1->1), (Tet, 0->2), 00876 //! (Hex, 2->2), (Hex, 1->1)(diagonally across element), (Hex, 0->0) (diagonally across element) 00877 //! All other parent types and child dimensions return an error. 00878 //! 00879 //! \param parent_type The type of parent element 00880 //! \param child_type The type of child element 00881 //! \param child_index The index of the child element 00882 //! \param opposite_index The index of the opposite element 00883 //! \return status Returns 0 if successful, -1 if not 00884 void MBCN_OppositeSide( const int parent_type, 00885 const int child_index, 00886 const int child_dim, 00887 int* opposite_index, 00888 int* opposite_dim, 00889 int* rval ) 00890 { 00891 *rval = CN::OppositeSide( (EntityType)parent_type, child_index, child_dim, *opposite_index, *opposite_dim ); 00892 } 00893 00894 //! given two connectivity arrays, determine whether or not they represent the same entity. 00895 //! \param conn1 Connectivity array of first entity 00896 //! \param conn2 Connectivity array of second entity 00897 //! \param num_vertices Number of entries in <em>conn1</em> and <em>conn2</em> 00898 //! \param direct If positive, entities have the same sense (returned) 00899 //! \param offset Offset of <em>conn2</em>'s first vertex in <em>conn1</em> 00900 //! \return rval Returns true if <em>conn1</em> and <em>conn2</em> match 00901 void MBCN_ConnectivityMatchInt( const int* conn1, 00902 const int* conn2, 00903 const int num_vertices, 00904 int* direct, 00905 int* offset, 00906 int* rval ) 00907 { 00908 *rval = CN::ConnectivityMatch( conn1, conn2, num_vertices, *direct, *offset ); 00909 } 00910 00911 void MBCN_ConnectivityMatchUint( const unsigned int* conn1, 00912 const unsigned int* conn2, 00913 const int num_vertices, 00914 int* direct, 00915 int* offset, 00916 int* rval ) 00917 { 00918 *rval = CN::ConnectivityMatch( conn1, conn2, num_vertices, *direct, *offset ); 00919 } 00920 00921 void MBCN_ConnectivityMatchLong( const long* conn1, 00922 const long* conn2, 00923 const int num_vertices, 00924 int* direct, 00925 int* offset, 00926 int* rval ) 00927 { 00928 *rval = CN::ConnectivityMatch( conn1, conn2, num_vertices, *direct, *offset ); 00929 } 00930 00931 void MBCN_ConnectivityMatchUlong( const unsigned long* conn1, 00932 const unsigned long* conn2, 00933 const int num_vertices, 00934 int* direct, 00935 int* offset, 00936 int* rval ) 00937 { 00938 *rval = CN::ConnectivityMatch( conn1, conn2, num_vertices, *direct, *offset ); 00939 } 00940 00941 void MBCN_ConnectivityMatchVoid( void* const* conn1, 00942 void* const* conn2, 00943 const int num_vertices, 00944 int* direct, 00945 int* offset, 00946 int* rval ) 00947 { 00948 *rval = CN::ConnectivityMatch( conn1, conn2, num_vertices, *direct, *offset ); 00949 } 00950 00951 //! true if entities of a given type and number of nodes indicates mid edge nodes are present. 00952 //! \param this_type Type of entity for which sub-entity connectivity is being queried 00953 //! \param num_verts Number of nodes defining entity 00954 //! \return int Returns true if <em>this_type</em> combined with <em>num_nodes</em> indicates 00955 //! mid-edge nodes are likely 00956 void MBCN_HasMidEdgeNodes( const int this_type, const int num_verts, int* rval ) 00957 { 00958 *rval = CN::HasMidEdgeNodes( (EntityType)this_type, num_verts ); 00959 } 00960 00961 //! true if entities of a given type and number of nodes indicates mid face nodes are present. 00962 //! \param this_type Type of entity for which sub-entity connectivity is being queried 00963 //! \param num_verts Number of nodes defining entity 00964 //! \return int Returns true if <em>this_type</em> combined with <em>num_nodes</em> indicates 00965 //! mid-face nodes are likely 00966 void MBCN_HasMidFaceNodes( const int this_type, const int num_verts, int* rval ) 00967 { 00968 *rval = CN::HasMidFaceNodes( (EntityType)this_type, num_verts ); 00969 } 00970 00971 //! true if entities of a given type and number of nodes indicates mid region nodes are present. 00972 //! \param this_type Type of entity for which sub-entity connectivity is being queried 00973 //! \param num_verts Number of nodes defining entity 00974 //! \return int Returns true if <em>this_type</em> combined with <em>num_nodes</em> indicates 00975 //! mid-region nodes are likely 00976 void MBCN_HasMidRegionNodes( const int this_type, const int num_verts, int* rval ) 00977 { 00978 *rval = CN::HasMidRegionNodes( (EntityType)this_type, num_verts ); 00979 } 00980 00981 //! true if entities of a given type and number of nodes indicates mid edge/face/region nodes 00982 //! are present. 00983 //! \param this_type Type of entity for which sub-entity connectivity is being queried 00984 //! \param num_verts Number of nodes defining entity 00985 //! \param mid_nodes If <em>mid_nodes[i], i=1..3</em> is true, indicates that mid-edge 00986 //! (i=1), mid-face (i=2), and/or mid-region (i=3) nodes are likely 00987 void MBCN_HasMidNodes( const int this_type, const int num_verts, int mid_nodes[4] ) 00988 { 00989 return CN::HasMidNodes( (EntityType)this_type, num_verts, mid_nodes ); 00990 } 00991 00992 //! given data about an element and a vertex in that element, return the dimension 00993 //! and index of the sub-entity that the vertex resolves. If it does not resolve a 00994 //! sub-entity, either because it's a corner node or it's not in the element, -1 is 00995 //! returned in both return values. 00996 //! \param elem_type Type of entity being queried 00997 //! \param num_nodes The number of nodes in the element connectivity 00998 //! \param ho_node_index The position of the HO node in the connectivity list (zero based) 00999 //! \param parent_dim Dimension of sub-entity high-order node resolves (returned) 01000 //! \param parent_index Index of sub-entity high-order node resolves (returned) 01001 void MBCN_HONodeParent( int elem_type, int num_nodes, int ho_node_index, int* parent_dim, int* parent_index ) 01002 { 01003 return CN::HONodeParent( (EntityType)elem_type, num_nodes, ho_node_index, *parent_dim, *parent_index ); 01004 } 01005 01006 //! for an entity of this type with num_verts vertices, and a specified subfacet 01007 //! (dimension and index), return the index of the higher order node for that entity 01008 //! in this entity's connectivity array 01009 //! \param this_type Type of entity being queried 01010 //! \param num_verts Number of vertices for the entity being queried 01011 //! \param subfacet_dim Dimension of sub-entity being queried 01012 //! \param subfacet_index Index of sub-entity being queried 01013 //! \return index Index of sub-entity's higher-order node 01014 void MBCN_HONodeIndex( const int this_type, 01015 const int num_verts, 01016 const int subfacet_dim, 01017 const int subfacet_index, 01018 int* rval ) 01019 01020 { 01021 01022 *rval = CN::HONodeIndex( (EntityType)this_type, num_verts, subfacet_dim, subfacet_index ); 01023 } 01024 01025 namespace moab 01026 { 01027 01028 template < typename T > 01029 inline int permute_this( EntityType t, const int dim, T* conn, const int indices_per_ent, const int num_entries ) 01030 { 01031 T tmp_conn[MAX_SUB_ENTITIES]; 01032 assert( indices_per_ent <= CN::permuteVec[t][dim][MAX_SUB_ENTITIES] ); 01033 if( indices_per_ent > CN::permuteVec[t][dim][MAX_SUB_ENTITIES] ) return 1; 01034 short int* tvec = CN::permuteVec[t][dim]; 01035 T* pvec = conn; 01036 for( int j = 0; j < num_entries; j++ ) 01037 { 01038 for( int i = 0; i < indices_per_ent; i++ ) 01039 tmp_conn[tvec[i]] = pvec[i]; 01040 memcpy( pvec, tmp_conn, indices_per_ent * sizeof( T ) ); 01041 pvec += indices_per_ent; 01042 } 01043 01044 return 0; 01045 } 01046 01047 template < typename T > 01048 inline int rev_permute_this( EntityType t, const int dim, T* conn, const int indices_per_ent, const int num_entries ) 01049 { 01050 T tmp_conn[MAX_SUB_ENTITIES]; 01051 assert( indices_per_ent <= CN::revPermuteVec[t][dim][MAX_SUB_ENTITIES] ); 01052 if( indices_per_ent > CN::revPermuteVec[t][dim][MAX_SUB_ENTITIES] ) return 1; 01053 short int* tvec = CN::revPermuteVec[t][dim]; 01054 T* pvec = conn; 01055 for( int j = 0; j < num_entries; j++ ) 01056 { 01057 for( int i = 0; i < indices_per_ent; i++ ) 01058 tmp_conn[i] = pvec[tvec[i]]; 01059 memcpy( pvec, tmp_conn, indices_per_ent * sizeof( T ) ); 01060 pvec += indices_per_ent; 01061 } 01062 01063 return 0; 01064 } 01065 01066 short int CN::Dimension( const EntityType t ) 01067 { 01068 return mConnectivityMap[t][0].topo_dimension; 01069 } 01070 01071 short int CN::VerticesPerEntity( const EntityType t ) 01072 { 01073 return ( MBVERTEX == t 01074 ? (short int)1 01075 : mConnectivityMap[t][mConnectivityMap[t][0].topo_dimension - 1].num_corners_per_sub_element[0] ); 01076 } 01077 01078 short int CN::NumSubEntities( const EntityType t, const int d ) 01079 { 01080 return ( t != MBVERTEX && d > 0 ? mConnectivityMap[t][d - 1].num_sub_elements 01081 : ( d ? (short int)-1 : VerticesPerEntity( t ) ) ); 01082 } 01083 01084 //! return the type of a particular sub-entity. 01085 EntityType CN::SubEntityType( const EntityType this_type, const int sub_dimension, const int index ) 01086 { 01087 return ( !sub_dimension ? MBVERTEX 01088 : ( Dimension( this_type ) == sub_dimension && 0 == index 01089 ? this_type 01090 : mConnectivityMap[this_type][sub_dimension - 1].target_type[index] ) ); 01091 } 01092 01093 const short* CN::SubEntityVertexIndices( const EntityType this_type, 01094 const int sub_dimension, 01095 const int index, 01096 EntityType& sub_type, 01097 int& n ) 01098 { 01099 if( sub_dimension == 0 ) 01100 { 01101 n = 1; 01102 sub_type = MBVERTEX; 01103 return increasingInts + index; 01104 } 01105 else 01106 { 01107 const CN::ConnMap& map = mConnectivityMap[this_type][sub_dimension - 1]; 01108 sub_type = map.target_type[index]; 01109 n = map.num_corners_per_sub_element[index]; 01110 return map.conn[index]; 01111 } 01112 } 01113 01114 //! Permute this vector 01115 inline int CN::permuteThis( const EntityType t, const int dim, int* pvec, const int num_indices, const int num_entries ) 01116 { 01117 return permute_this( t, dim, pvec, num_indices, num_entries ); 01118 } 01119 inline int CN::permuteThis( const EntityType t, 01120 const int dim, 01121 unsigned int* pvec, 01122 const int num_indices, 01123 const int num_entries ) 01124 { 01125 return permute_this( t, dim, pvec, num_indices, num_entries ); 01126 } 01127 inline int CN::permuteThis( const EntityType t, 01128 const int dim, 01129 long* pvec, 01130 const int num_indices, 01131 const int num_entries ) 01132 { 01133 return permute_this( t, dim, pvec, num_indices, num_entries ); 01134 } 01135 inline int CN::permuteThis( const EntityType t, 01136 const int dim, 01137 void** pvec, 01138 const int num_indices, 01139 const int num_entries ) 01140 { 01141 return permute_this( t, dim, pvec, num_indices, num_entries ); 01142 } 01143 01144 //! Reverse permute this vector 01145 inline int CN::revPermuteThis( const EntityType t, 01146 const int dim, 01147 int* pvec, 01148 const int num_indices, 01149 const int num_entries ) 01150 { 01151 return rev_permute_this( t, dim, pvec, num_indices, num_entries ); 01152 } 01153 inline int CN::revPermuteThis( const EntityType t, 01154 const int dim, 01155 unsigned int* pvec, 01156 const int num_indices, 01157 const int num_entries ) 01158 { 01159 return rev_permute_this( t, dim, pvec, num_indices, num_entries ); 01160 } 01161 inline int CN::revPermuteThis( const EntityType t, 01162 const int dim, 01163 long* pvec, 01164 const int num_indices, 01165 const int num_entries ) 01166 { 01167 return rev_permute_this( t, dim, pvec, num_indices, num_entries ); 01168 } 01169 inline int CN::revPermuteThis( const EntityType t, 01170 const int dim, 01171 void** pvec, 01172 const int num_indices, 01173 const int num_entries ) 01174 { 01175 return rev_permute_this( t, dim, pvec, num_indices, num_entries ); 01176 } 01177 01178 } // namespace moab